Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

A63 Fix: Sort Imports by dependencies #39

Merged
merged 1 commit into from
Sep 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,17 @@ impl AmberCompiler {
}

pub fn translate(&self, block: Block, meta: ParserMetadata) -> String {
let imports_sorted = meta.import_history.topological_sort();
let imports_blocks = meta.import_history.import_map.clone();
let mut meta = TranslateMetadata::new(&meta);
block.translate(&mut meta)
let mut result = vec![];
for index in imports_sorted.iter() {
if *index != 0 {
result.push(imports_blocks[*index - 1].translate(&mut meta));
}
}
result.push(block.translate(&mut meta));
result.join("\n")
}

pub fn compile(&self) -> Result<(String, Vec<Message>), Message> {
Expand Down
32 changes: 19 additions & 13 deletions src/modules/imports/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ use super::import_string::ImportString;

#[derive(Debug, Clone)]
pub struct Import {
path: ImportString,
block: Block
path: ImportString
}

impl Import {
Expand All @@ -28,6 +27,16 @@ impl Import {
}
}

fn add_import(&mut self, meta: &mut ParserMetadata, tok: Option<Token>, path: &str) -> SyntaxResult {
if meta.import_history.add_import(meta.get_path(), path.to_string()).is_none() {
return error!(meta, tok => {
message: "Circular import detected",
comment: "Please remove the circular import"
})
}
Ok(())
}

fn resolve_path(&mut self, meta: &mut ParserMetadata, tok: Option<Token>) -> Result<String, Failure> {
let mut path = meta.path.as_ref()
.map_or_else(|| Path::new("."), |path| Path::new(path))
Expand All @@ -36,12 +45,7 @@ impl Import {
path.push(&self.path.value);
match path.to_str() {
Some(path) => {
if meta.import_history.add_import(meta.path.clone(), path.to_string()).is_none() {
return error!(meta, tok => {
message: "Circular import detected",
comment: "Please remove the circular import"
})
}
self.add_import(meta, tok, path)?;
Ok(path.to_string())
}
None => error!(meta, tok => {
Expand All @@ -64,6 +68,7 @@ impl Import {
fn handle_import(&mut self, meta: &mut ParserMetadata, tok: Option<Token>, imported_code: String) -> SyntaxResult {
match AmberCompiler::new(imported_code.clone(), Some(self.path.value.clone())).tokenize() {
Ok(tokens) => {
let mut block = Block::new();
// Save snapshot of current file
let code = meta.code.clone();
let path = meta.path.clone();
Expand All @@ -78,8 +83,9 @@ impl Import {
meta.expr = tokens;
meta.set_index(0);
meta.mem.scopes = vec![];
syntax(meta, &mut self.block)?;
syntax(meta, &mut block)?;
meta.mem.scopes = scopes;
meta.import_history.import_map.push(block);
self.handle_export(meta, meta.mem.exports.clone());
// Restore snapshot of current file
meta.code = code;
Expand All @@ -102,8 +108,7 @@ impl SyntaxModule<ParserMetadata> for Import {

fn new() -> Self {
Self {
path: ImportString::new(),
block: Block::new()
path: ImportString::new()
}
}

Expand All @@ -115,6 +120,7 @@ impl SyntaxModule<ParserMetadata> for Import {
let tok_str = meta.get_current_token();
syntax(meta, &mut self.path)?;
let imported_code = if self.path.value == "[standard library]" {
self.add_import(meta, tok_str, "[standard library]")?;
AmberCompiler::import_std()
} else {
self.resolve_import(meta, tok_str)?
Expand All @@ -125,7 +131,7 @@ impl SyntaxModule<ParserMetadata> for Import {
}

impl TranslateModule for Import {
fn translate(&self, meta: &mut TranslateMetadata) -> String {
self.block.translate(meta)
fn translate(&self, _meta: &mut TranslateMetadata) -> String {
"".to_string()
}
}
25 changes: 23 additions & 2 deletions src/utils/import_history.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use crate::modules::block::Block;

#[derive(Debug, Clone)]
pub struct ImportHistory {
pub imports: Vec<String>,
pub import_graph: Vec<Vec<usize>>
pub import_graph: Vec<Vec<usize>>,
pub import_map: Vec<Block>
}

impl ImportHistory {
Expand All @@ -17,7 +20,8 @@ impl ImportHistory {
pub fn new(initial_path: Option<String>) -> Self {
ImportHistory {
imports: vec![Self::get_path(initial_path)],
import_graph: vec![vec![]]
import_graph: vec![vec![]],
import_map: vec![]
}
}

Expand Down Expand Up @@ -62,4 +66,21 @@ impl ImportHistory {
}
}
}

fn topological_sort_util(&self, v: usize, visited: &mut Vec<bool>, stack: &mut Vec<usize>) {
visited[v] = true;
for i in self.import_graph[v].iter() {
if !visited[*i] {
self.topological_sort_util(*i, visited, stack);
}
}
stack.push(v);
}

pub fn topological_sort(&self) -> Vec<usize> {
let mut stack = Vec::new();
let mut visited = vec![false; self.imports.len()];
self.topological_sort_util(0, &mut visited, &mut stack);
stack
}
}