Skip to content

Commit

Permalink
Fixed FlattenedModules being doubly flattened
Browse files Browse the repository at this point in the history
  • Loading branch information
VonTum committed Dec 2, 2023
1 parent 9d24ff7 commit bf83bf0
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 57 deletions.
24 changes: 22 additions & 2 deletions src/ast.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

use num::bigint::BigUint;

use crate::{tokenizer::{TokenTypeIdx, get_token_type_name}, linker::{NamedUUID, FileUUID}, flattening::{FlattenedModule, FlattenedInterface}, arena_alloc::{UUIDMarker, UUID, FlatAlloc}, instantiation::InstantiationList};
use crate::{tokenizer::{TokenTypeIdx, get_token_type_name}, linker::{NamedUUID, FileUUID, Linker}, flattening::{FlattenedModule, FlattenedInterface}, arena_alloc::{UUIDMarker, UUID, FlatAlloc}, instantiation::InstantiationList};
use core::ops::Range;
use std::fmt::Display;

Expand All @@ -12,7 +12,7 @@ pub struct Span(pub usize, pub usize);

#[derive(Debug,Clone,Copy,PartialEq,Eq,Hash)]
pub struct DeclIDMarker;
impl UUIDMarker for DeclIDMarker {const DISPLAY_NAME : &'static str = "obj_";}
impl UUIDMarker for DeclIDMarker {const DISPLAY_NAME : &'static str = "decl_";}
pub type DeclID = UUID<DeclIDMarker>;


Expand Down Expand Up @@ -158,6 +158,26 @@ pub struct Module {
pub instantiations : InstantiationList
}

impl Module {
pub fn print_flattened_module(&self, linker : &Linker) {
println!("Interface:");
for port in &self.interface.interface_wires {
let port_direction = if port.is_input {"input"} else {"output"};
let port_type = port.typ.to_string(linker);
let port_name = &port.port_name;
println!(" {port_direction} {port_type} {port_name} -> {:?}", port.wire_id);
}
println!("Instantiations:");
for (id, inst) in &self.flattened.instantiations {
println!(" {:?}: {:?}", id, inst);
}
println!("Connections:");
for conn in &self.flattened.connections {
println!(" {:?}", conn);
}
}
}

#[derive(Debug,Clone,Copy)]
pub struct GlobalReference(pub Span, pub NamedUUID); // token index, and name span

Expand Down
6 changes: 3 additions & 3 deletions src/dev_aid/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl LoadedFileCache {
} else {
self.linker.relink(file_uuid, full_parse, parsing_errors);
}
self.linker.flatten_all_modules();
self.linker.recompile_all();
}
fn ensure_contains_file(&mut self, uri : &Url) -> FileUUID {
if let Some(found) = self.find_uri(uri) {
Expand All @@ -47,7 +47,7 @@ impl LoadedFileCache {
let (full_parse, parsing_errors) = perform_full_semantic_parse(file_text, file_uuid);
self.linker.add_reserved_file(file_uuid, full_parse, parsing_errors);
self.uris.insert(file_uuid, uri.clone());
self.linker.flatten_all_modules();
self.linker.recompile_all();
file_uuid
}
}
Expand Down Expand Up @@ -337,7 +337,7 @@ fn main_loop(
}))?;

// println!("Flattening...");
file_cache.linker.flatten_all_modules();
file_cache.linker.recompile_all();

let mut errors = file_cache.linker.files[uuid].parsing_errors.clone();
file_cache.linker.get_all_errors_in_file(uuid, &mut errors);
Expand Down
2 changes: 1 addition & 1 deletion src/dev_aid/syntax_highlighting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ pub fn syntax_highlight_file(file_paths : Vec<PathBuf>, settings : &SyntaxHighli

let mut file_cache : FileCache = Default::default();

linker.flatten_all_modules();
linker.recompile_all();

for (file_uuid, f) in &linker.files {
if settings.show_tokens {
Expand Down
13 changes: 10 additions & 3 deletions src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@


use std::{ops::Range, path::{Path, PathBuf}, cell::RefCell};
use std::{ops::Range, path::{Path, PathBuf}, cell::{RefCell, Cell}};

use crate::{ast::Span, linker::{FileUUID, FileUUIDMarker}, arena_alloc::ArenaVector};
use ariadne::*;
Expand Down Expand Up @@ -108,20 +108,23 @@ pub fn join_expected_list(expected : &[TokenTypeIdx]) -> String {
#[derive(Debug,Clone)]
pub struct ErrorCollector {
errors : RefCell<Vec<CompileError>>,
pub file : FileUUID
did_error : Cell<bool>,
pub file : FileUUID,
}

impl ErrorCollector {
pub fn new(file : FileUUID) -> Self {
Self{errors : RefCell::new(Vec::new()), file}
Self{errors : RefCell::new(Vec::new()), file, did_error : Cell::new(false)}
}

pub fn error_basic<S : Into<String>>(&self, position : Span, reason : S) {
self.errors.borrow_mut().push(CompileError{position, reason : reason.into(), infos : Vec::new(), level : ErrorLevel::Error});
self.did_error.set(true);
}

pub fn error_with_info<S : Into<String>>(&self, position : Span, reason : S, infos : Vec<ErrorInfo>) {
self.errors.borrow_mut().push(CompileError{position, reason : reason.into(), infos : infos, level : ErrorLevel::Error});
self.did_error.set(true);
}

pub fn warn_basic<S : Into<String>>(&self, position : Span, reason : S) {
Expand All @@ -140,4 +143,8 @@ impl ErrorCollector {
assert!(self.file == source.file);
self.errors.borrow_mut().extend_from_slice(&source.errors.borrow());
}

pub fn did_error(&self) -> bool {
self.did_error.get()
}
}
71 changes: 46 additions & 25 deletions src/flattening.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,18 @@ impl Instantiation {

pub fn iter_sources<F : FnMut(FlatID) -> ()>(&self, mut f : F) {
match self {
Instantiation::SubModule { module_uuid, typ_span, interface_wires } => {
Instantiation::SubModule { module_uuid : _, typ_span : _, interface_wires } => {
for port in interface_wires {
if port.is_input {
f(port.id);
}
}
}
Instantiation::PlainWire { read_only, typ, decl_id } => {}
Instantiation::UnaryOp { typ, op, right } => {f(right.0);}
Instantiation::BinaryOp { typ, op, left, right } => {f(left.0); f(right.0);}
Instantiation::ArrayAccess { typ, arr, arr_idx } => {f(arr.0); f(arr_idx.0)}
Instantiation::Constant { typ, value } => {}
Instantiation::PlainWire { read_only : _, typ : _, decl_id : _ } => {}
Instantiation::UnaryOp { typ : _, op : _, right } => {f(right.0);}
Instantiation::BinaryOp { typ : _, op : _, left, right } => {f(left.0); f(right.0);}
Instantiation::ArrayAccess { typ : _, arr, arr_idx } => {f(arr.0); f(arr_idx.0)}
Instantiation::Constant { typ : _, value : _ } => {}
Instantiation::Error => {}
}
}
Expand Down Expand Up @@ -441,14 +441,20 @@ impl FlattenedModule {
Produces an initial FlattenedModule, in which the interface types have already been resolved.
Must be further processed by flatten, but this requires all modules to have been Initial Flattened for dependency resolution
*/
pub fn initialize_interfaces(&self, linker : &Linker, module : &Module) -> (FlattenedInterface, FlatAlloc<FlatID, DeclIDMarker>) {
pub fn initialize_interfaces(linker : &Linker, module : &Module) -> (FlattenedInterface, FlattenedModule, FlatAlloc<FlatID, DeclIDMarker>) {
let mut interface = FlattenedInterface::new();

let flat_mod = FlattenedModule {
instantiations: ListAllocator::new(),
connections: BlockVec::new(),
errors: ErrorCollector::new(module.link_info.file)
};

let mut context = FlatteningContext{
decl_to_flat_map: module.declarations.iter().map(|_| UUID::INVALID).collect(),
instantiations: &self.instantiations,
connections: &self.connections,
errors: &self.errors,
instantiations: &flat_mod.instantiations,
connections: &flat_mod.connections,
errors: &flat_mod.errors,
linker,
module,
};
Expand All @@ -461,7 +467,7 @@ impl FlattenedModule {
};

let (wire_id, typ) = if let Some(typ) = context.map_to_type(&decl.typ.0, &module.link_info.global_references) {
let wire_id = self.instantiations.alloc(Instantiation::PlainWire { read_only: is_input, typ : typ.clone(), decl_id : Some(decl_id)});
let wire_id = context.instantiations.alloc(Instantiation::PlainWire { read_only: is_input, typ : typ.clone(), decl_id : Some(decl_id)});
(wire_id, typ)
} else {
(UUID::INVALID, Type::Named(UUID::INVALID))
Expand All @@ -470,7 +476,8 @@ impl FlattenedModule {
context.decl_to_flat_map[decl_id] = wire_id;
}

(interface, context.decl_to_flat_map)
let decl_to_flat_map = context.decl_to_flat_map;
(interface, flat_mod, decl_to_flat_map)
}

/*
Expand All @@ -493,16 +500,13 @@ impl FlattenedModule {

pub fn find_unused_variables(&self, md : &Module) {
// Setup Wire Fanouts List for faster processing
let mut wire_fanouts : FlatAlloc<Vec<FlatID>, FlatIDMarker> = self.instantiations.iter().map(|_| Vec::new()).collect();

for (id, w) in &self.instantiations {
w.iter_sources(|s_id| {
wire_fanouts[s_id].push(id);
});
}
let mut connection_fanin : FlatAlloc<Vec<FlatID>, FlatIDMarker> = self.instantiations.iter().map(|_| Vec::new()).collect();

for conn in &self.connections {
wire_fanouts[conn.from.0].push(conn.to.root);
connection_fanin[conn.to.root].push(conn.from.0);
if conn.condition != UUID::INVALID {
connection_fanin[conn.to.root].push(conn.condition);
}
}

let mut is_instance_used_map : FlatAlloc<bool, FlatIDMarker> = self.instantiations.iter().map(|_| false).collect();
Expand All @@ -516,20 +520,37 @@ impl FlattenedModule {
}
}

println!("Pre Explore");
println!("{:?}", connection_fanin);
println!("{:?}", is_instance_used_map);
println!("{:?}", wire_to_explore_queue);

while let Some(item) = wire_to_explore_queue.pop() {
for to in &wire_fanouts[item] {
if !is_instance_used_map[*to] {
is_instance_used_map[*to] = true;
wire_to_explore_queue.push(*to);
let wire = &self.instantiations[item];
wire.iter_sources(|from| {
if !is_instance_used_map[from] {
is_instance_used_map[from] = true;
wire_to_explore_queue.push(from);
}
});
for from in &connection_fanin[item] {
if !is_instance_used_map[*from] {
is_instance_used_map[*from] = true;
wire_to_explore_queue.push(*from);
}
}
}

println!("Final");
println!("{:?}", connection_fanin);
println!("{:?}", is_instance_used_map);
println!("{:?}", wire_to_explore_queue);

// Now produce warnings from the unused list
for (id, inst) in &self.instantiations {
if !is_instance_used_map[id] {
if let Instantiation::PlainWire { read_only : _, typ : _, decl_id : Some(decl_id) } = inst {
self.errors.warn_basic(Span::from(md.declarations[*decl_id].name_token), "Unused variable");
self.errors.warn_basic(Span::from(md.declarations[*decl_id].name_token), "Unused Variable: This variable does not affect the output ports of this module");
}
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/instantiation.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{rc::Rc, ops::Deref, cell::RefCell, iter::zip};
use std::{rc::Rc, ops::Deref, cell::RefCell};

use crate::{arena_alloc::{UUID, UUIDMarker, FlatAlloc}, ast::{Value, Operator, Module}, typing::{ConcreteType, Type}, flattening::{FlatID, Instantiation, FlatIDMarker, ConnectionWrite, ConnectionWritePathElement, InterfacePort}, errors::ErrorCollector, linker::{Linker, get_builtin_uuid, NamedUUID}};

Expand Down Expand Up @@ -259,6 +259,10 @@ impl InstantiationList {
errors.ingest(&inst.errors);
}
}

pub fn clear_instances(&mut self) {
self.cache.borrow_mut().clear()
}
}


36 changes: 18 additions & 18 deletions src/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,48 +498,48 @@ impl Linker {
}
}

pub fn flatten_all_modules(&mut self) {
pub fn recompile_all(&mut self) {
// First create initial flattening for everything, to produce the necessary interfaces

let mut interface_vec : Vec<(NamedUUID, FlattenedInterface)> = Vec::new();
let mut flattened_vec : Vec<(NamedUUID, FlatAlloc<FlatID, DeclIDMarker>)> = Vec::new();
let mut interface_vec : Vec<(NamedUUID, FlattenedInterface, FlattenedModule)> = Vec::new();
let mut initial_flat_vec : Vec<(NamedUUID, FlatAlloc<FlatID, DeclIDMarker>)> = Vec::new();
for (id, named_object) in &self.links.globals {
println!("Initializing Flattening for {}", named_object.get_name());
println!("Initializing Interface for {}", named_object.get_name());
if let Named::Module(md) = named_object {
// Do initial flattening for ALL modules, regardless of linking errors, to get proper interface
// if !md.link_info.is_fully_linked {continue;}
let (interface, decl_to_flat_map) = md.flattened.initialize_interfaces(&self, md);
interface_vec.push((id, interface));
flattened_vec.push((id, decl_to_flat_map));
let (interface, flattened, decl_to_flat_map) = FlattenedModule::initialize_interfaces(&self, md);
interface_vec.push((id, interface, flattened));
initial_flat_vec.push((id, decl_to_flat_map));
}
}

for (id, interface) in interface_vec {
for (id, interface, flattened) in interface_vec {
let Named::Module(md) = &mut self.links.globals[id] else {unreachable!()};

md.interface = interface;
md.flattened = flattened;
md.instantiations.clear_instances();
}

// Then do proper flattening on every module
for (id, decl_to_flat_map) in flattened_vec {
for (id, decl_to_flat_map) in initial_flat_vec {
let Named::Module(md) = &self.links.globals[id] else {unreachable!()};

println!("Flattening {}", &md.link_info.name);
// Do check for linking errors when generating code, as this could cause the compiler to error
if !md.link_info.is_fully_linked {continue;}
md.flattened.flatten(md, &self, decl_to_flat_map);
md.flattened.find_unused_variables(md);
}

println!("[[{}]]:", md.link_info.name);
println!("\tInstantiations:");
for (id, inst) in &md.flattened.instantiations {
println!("\t\t{:?}: {:?}", id, inst);
}
println!("\tConnections:");
for conn in &md.flattened.connections {
println!("\t\t{:?}", conn);
// Can't merge these loops
for (id, named_object) in &self.links.globals {
if let Named::Module(md) = named_object {
println!("[[{}]]:", md.link_info.name);
md.print_flattened_module(self);
let inst = self.instantiate(id);
}
self.instantiate(id);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ fn main() -> Result<(), Box<dyn Error + Sync + Send>> {
}
if file_paths.len() == 0 {
// Quick debug file
//file_paths.push(PathBuf::from("resetNormalizer.sus"));
file_paths.push(PathBuf::from("multiply_add.sus"));
file_paths.push(PathBuf::from("resetNormalizer.sus"));
//file_paths.push(PathBuf::from("multiply_add.sus"));
}
syntax_highlight_file(file_paths, &settings);

Expand Down
10 changes: 8 additions & 2 deletions src/typing.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::ops::Deref;

use crate::{ast::{Value, Operator, Span}, linker::{get_builtin_uuid, NamedUUID, Linker, Linkable}, tokenizer::kw, flattening::FlatID, errors::ErrorCollector};
use crate::{ast::{Value, Operator, Span}, linker::{get_builtin_uuid, NamedUUID, Linker, Linkable}, tokenizer::kw, flattening::FlatID, errors::ErrorCollector, arena_alloc::UUID};

// Types contain everything that cannot be expressed at runtime
#[derive(Debug, Clone, PartialEq, Eq)]
Expand All @@ -16,7 +16,13 @@ pub enum Type {
impl Type {
pub fn to_string(&self, linker : &Linker) -> String {
match self {
Type::Named(n) => linker.links[*n].get_full_name(),
Type::Named(n) => {
if *n == UUID::INVALID {
"{unknown}".to_owned()
} else {
linker.links[*n].get_full_name()
}
}
Type::Array(sub) => sub.deref().0.to_string(linker) + "[]",
}
}
Expand Down

0 comments on commit bf83bf0

Please sign in to comment.