Skip to content

Commit

Permalink
Further progess on linker endumb-ening
Browse files Browse the repository at this point in the history
  • Loading branch information
VonTum committed Jan 10, 2024
1 parent 0505b50 commit c248875
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 98 deletions.
4 changes: 2 additions & 2 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ impl From<usize> for Span {
#[derive(Debug, Clone, Copy)]
pub enum LocalOrGlobal {
Local(DeclID),
Global(usize)
Global(Span)
}


#[derive(Debug, Clone)]
pub enum TypeExpression {
Named(usize), // position in referenced globals list
Named, // SpanTypeExpression Span gives name
Array(Box<(SpanTypeExpression, SpanExpression)>)
}

Expand Down
6 changes: 3 additions & 3 deletions src/dev_aid/syntax_highlighting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,17 +123,17 @@ fn walk_name_color(all_objects : &[NamedUUID], links : &Links, result : &mut [ID
Instantiation::Wire(w) => {
if let &WireSource::WireRead{from_wire} = &w.source {
let decl = module.flattened.instantiations[from_wire].extract_wire_declaration();
if decl.is_remote_declaration.is_some() {continue;} // Virtual wires don't appear in this program text
if decl.is_remote_declaration {continue;} // Virtual wires don't appear in this program text
result[w.span.assert_is_single_token()].typ = IDETokenType::Identifier(IDEIdentifierType::Value(decl.identifier_type));
}
}
Instantiation::WireDeclaration(decl) => {
if decl.is_remote_declaration.is_some() {continue;} // Virtual wires don't appear in this program text
if decl.is_remote_declaration {continue;} // Virtual wires don't appear in this program text
result[decl.name_token].typ = IDETokenType::Identifier(IDEIdentifierType::Value(decl.identifier_type));
}
Instantiation::Connection(conn) => {
let decl = module.flattened.instantiations[conn.to.root].extract_wire_declaration();
if decl.is_remote_declaration.is_some() {continue;} // Virtual wires don't appear in this program text
if decl.is_remote_declaration {continue;} // Virtual wires don't appear in this program text
result[conn.to.span.0].typ = IDETokenType::Identifier(IDEIdentifierType::Value(decl.identifier_type));
}
Instantiation::SubModule(_) | Instantiation::IfStatement(_) | Instantiation::ForStatement(_) => {}
Expand Down
43 changes: 21 additions & 22 deletions src/flattening.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::{ops::{Deref, Range}, iter::zip, cell::{RefCell, Ref}};
use std::{ops::{Deref, Range}, iter::zip, cell::RefCell};

use crate::{
ast::{Span, Module, Expression, SpanExpression, LocalOrGlobal, Operator, AssignableExpression, SpanAssignableExpression, Statement, CodeBlock, IdentifierType, TypeExpression, DeclIDMarker, DeclID, SpanTypeExpression},
linker::{Linker, Named, Linkable, NamedUUID, FileUUID, GlobalResolver, ResolvedGlobals},
linker::{Linker, NamedUUID, FileUUID, GlobalResolver, ResolvedGlobals},
errors::{ErrorCollector, error_info}, arena_alloc::{UUID, UUIDMarker, FlatAlloc, UUIDRange}, typing::{Type, typecheck_unary_operator, get_binary_operator_types, typecheck, typecheck_is_array_indexer, BOOL_TYPE, INT_TYPE}, value::Value
};

Expand Down Expand Up @@ -31,7 +31,7 @@ pub struct ConnectionWrite {
pub root : FlatID,
pub path : Vec<ConnectionWritePathElement>,
pub span : Span,
pub is_remote_declaration : Option<NamedUUID>
pub is_remote_declaration : bool
}

#[derive(Debug)]
Expand Down Expand Up @@ -67,15 +67,15 @@ pub struct WireInstance {
pub typ : Type,
pub is_compiletime : bool,
pub span : Span,
pub is_remote_declaration : Option<NamedUUID>,
pub is_remote_declaration : bool,
pub source : WireSource
}

#[derive(Debug)]
pub struct WireDeclaration {
pub typ : Type,
pub typ_span : Span,
pub is_remote_declaration : Option<NamedUUID>,
pub is_remote_declaration : bool,
pub name_token : usize,
pub name : Box<str>,
pub read_only : bool,
Expand All @@ -94,7 +94,7 @@ pub struct SubModuleInstance {
pub module_uuid : NamedUUID,
pub name : Box<str>,
pub typ_span : Span,
pub is_remote_declaration : Option<NamedUUID>,
pub is_remote_declaration : bool,
pub outputs_start : usize,
pub local_wires : Box<[FlatID]>
}
Expand Down Expand Up @@ -167,7 +167,7 @@ impl Instantiation {
}
}

pub fn get_location(&self) -> Option<(Span, Option<NamedUUID>)> {
pub fn get_location(&self) -> Option<(Span, bool)> {
match self {
Instantiation::SubModule(sm) => Some((sm.typ_span, sm.is_remote_declaration)),
Instantiation::WireDeclaration(decl) => Some((decl.typ_span, decl.is_remote_declaration)),
Expand All @@ -182,7 +182,7 @@ struct FlatteningContext<'inst, 'l, 'm, 'resolved> {
decl_to_flat_map : FlatAlloc<Option<FlatID>, DeclIDMarker>,
instantiations : &'inst mut FlatAlloc<Instantiation, FlatIDMarker>,
errors : ErrorCollector,
is_remote_declaration : Option<NamedUUID>,
is_remote_declaration : bool,

linker : GlobalResolver<'l, 'resolved>,
module : &'m Module,
Expand All @@ -191,8 +191,8 @@ struct FlatteningContext<'inst, 'l, 'm, 'resolved> {
impl<'inst, 'l, 'm, 'resolved> FlatteningContext<'inst, 'l, 'm, 'resolved> {
fn map_to_type(&mut self, type_expr : &SpanTypeExpression) -> Type {
match &type_expr.0 {
TypeExpression::Named(n) => {
if let Some(typ_id) = &self.linker.try_get_type(self.module.link_info.global_references[*n], &self.errors) {
TypeExpression::Named => {
if let Some(typ_id) = &self.linker.try_get_type(type_expr.1, &self.errors) {
Type::Named(*typ_id)
} else {
Type::Error
Expand All @@ -217,8 +217,8 @@ impl<'inst, 'l, 'm, 'resolved> FlatteningContext<'inst, 'l, 'm, 'resolved> {
let decl = &self.module.declarations[decl_id];

if ONLY_ALLOW_TYPES {
if let TypeExpression::Named(n) = &decl.typ.0 {
if let Some(possible_module_ref) = self.module.link_info.global_references[*n].1 {
if let TypeExpression::Named = &decl.typ.0 {
if let Some(possible_module_ref) = self.linker.resolve_global(decl.typ.1, &self.errors) {
if let Some(md) = &self.linker.is_module(possible_module_ref) {
return self.alloc_module_interface(decl.name.clone(), md,possible_module_ref, decl.typ.1)
}
Expand Down Expand Up @@ -255,7 +255,7 @@ impl<'inst, 'l, 'm, 'resolved> FlatteningContext<'inst, 'l, 'm, 'resolved> {
decl_to_flat_map: module.declarations.iter().map(|_| None).collect(),
instantiations: self.instantiations,
errors: ErrorCollector::new(module.link_info.file), // Temporary ErrorCollector, unused
is_remote_declaration: Some(module_uuid),
is_remote_declaration: true,
linker: self.linker.new_sublinker(module.link_info.file),
module,
};
Expand All @@ -278,11 +278,11 @@ impl<'inst, 'l, 'm, 'resolved> FlatteningContext<'inst, 'l, 'm, 'resolved> {
Expression::Named(LocalOrGlobal::Local(l)) => {
self.decl_to_flat_map[*l].unwrap()
}
Expression::Named(LocalOrGlobal::Global(g)) => {
let module_ref = self.module.link_info.global_references[*g];
Expression::Named(LocalOrGlobal::Global(ref_span)) => {
let module_ref = self.linker.resolve_global(*ref_span, &self.errors)?;

let dependency = self.linker.try_get_module(module_ref, &self.errors)?;
self.alloc_module_interface(dependency.link_info.name.clone(), dependency, module_ref.1?, *name_expr_span)
let dependency = self.linker.try_get_module(*ref_span, &self.errors)?;
self.alloc_module_interface(dependency.link_info.name.clone(), dependency, module_ref, *name_expr_span)
}
_other => {
self.errors.error_basic(*name_expr_span, "Function call name cannot be an expression");
Expand Down Expand Up @@ -333,9 +333,8 @@ impl<'inst, 'l, 'm, 'resolved> FlatteningContext<'inst, 'l, 'm, 'resolved> {
let decl = self.instantiations[from_wire].extract_wire_declaration();
(decl.identifier_type == IdentifierType::Generative, WireSource::WireRead{from_wire})
}
Expression::Named(LocalOrGlobal::Global(g)) => {
let r = self.module.link_info.global_references[*g];
let cst = self.linker.try_get_constant(r, &self.errors)?;
Expression::Named(LocalOrGlobal::Global(ref_span)) => {
let cst = self.linker.try_get_constant(*ref_span, &self.errors)?;
(true, WireSource::Constant{value : cst})
}
Expression::Constant(cst) => {
Expand Down Expand Up @@ -553,7 +552,7 @@ impl FlattenedModule {
decl_to_flat_map: module.declarations.iter().map(|_| None).collect(),
instantiations: &mut instantiations,
errors: ErrorCollector::new(module.link_info.file),
is_remote_declaration : None,
is_remote_declaration : false,
linker : GlobalResolver::new(linker, module.link_info.file, &resolved_globals),
module,
};
Expand Down Expand Up @@ -742,7 +741,7 @@ impl FlattenedModule {
for (id, inst) in &self.instantiations {
if !is_instance_used_map[id] {
if let Instantiation::WireDeclaration(decl) = inst {
if decl.is_remote_declaration.is_none() {
if !decl.is_remote_declaration {
self.errors.warn_basic(Span::from(decl.name_token), "Unused Variable: This variable does not affect the output ports of this module");
}
}
Expand Down
118 changes: 56 additions & 62 deletions src/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,15 +495,18 @@ impl<'linker, 'resolved_list> GlobalResolver<'linker, 'resolved_list> {
GlobalResolver{linker : self.linker, file : &self.linker.files[file_id], resolved_globals : self.resolved_globals}
}

pub fn resolve_global(&self, name : Span) -> Option<NamedUUID> {
let name = self.file.get_token_text(name.assert_is_single_token());
pub fn resolve_global(&self, name_span : Span, errors : &ErrorCollector) -> Option<NamedUUID> {
let name = self.file.get_token_text(name_span.assert_is_single_token());

let mut resolved_globals = self.resolved_globals.borrow_mut();
if let Some(found) = self.linker.links.global_namespace.get(name) {
resolved_globals.referenced_globals.push(*found);
Some(*found)
} else {
resolved_globals.all_resolved = false;

errors.error_basic(name_span, format!("No Value or Type of the name '{name}' was found. Did you forget to import it?"));

None
}
}
Expand All @@ -520,75 +523,66 @@ impl<'linker, 'resolved_list> GlobalResolver<'linker, 'resolved_list> {
}
}

pub fn try_get_constant(&self, GlobalReference(identifier_span, ref_uuid) : GlobalReference, errors : &ErrorCollector) -> Option<Value> {
if let Some(uuid) = ref_uuid {
match &self.linker.links.globals[uuid] {
Named::Constant(NamedConstant::Builtin(_name, v)) => {
Some(v.clone())
},
other => {
let info = other.get_linking_error_location();
let infos = if let Some((file, span)) = info.location {
vec![error_info(span, file, "Defined here")]
} else {
vec![]
};
let name = info.name;
let ident_type = info.named_type;
errors.error_with_info(identifier_span, format!("{ident_type} {name} is not a Constant!"), infos);
None
}
pub fn try_get_constant(&self, identifier_span : Span, errors : &ErrorCollector) -> Option<Value> {
let uuid = self.resolve_global(identifier_span, errors)?;
match &self.linker.links.globals[uuid] {
Named::Constant(NamedConstant::Builtin(_name, v)) => {
Some(v.clone())
},
other => {
let info = other.get_linking_error_location();
let infos = if let Some((file, span)) = info.location {
vec![error_info(span, file, "Defined here")]
} else {
vec![]
};
let name = info.name;
let ident_type = info.named_type;
errors.error_with_info(identifier_span, format!("{ident_type} {name} is not a Constant!"), infos);
None
}
} else {
None
}
}

pub fn try_get_type(&self, GlobalReference(identifier_span, ref_uuid) : GlobalReference, errors : &ErrorCollector) -> Option<NamedUUID> {
if let Some(uuid) = ref_uuid {
match &self.linker.links.globals[uuid] {
Named::Type(_t) => {
Some(uuid)
},
other => {
let info = other.get_linking_error_location();
let infos = if let Some((file, span)) = info.location {
vec![error_info(span, file, "Defined here")]
} else {
vec![]
};
let name = info.name;
let ident_type = info.named_type;
errors.error_with_info(identifier_span, format!("{ident_type} {name} is not a Type!"), infos);
None
}
pub fn try_get_type(&self, identifier_span : Span, errors : &ErrorCollector) -> Option<NamedUUID> {
let uuid = self.resolve_global(identifier_span, errors)?;
match &self.linker.links.globals[uuid] {
Named::Type(_t) => {
Some(uuid)
},
other => {
let info = other.get_linking_error_location();
let infos = if let Some((file, span)) = info.location {
vec![error_info(span, file, "Defined here")]
} else {
vec![]
};
let name = info.name;
let ident_type = info.named_type;
errors.error_with_info(identifier_span, format!("{ident_type} {name} is not a Type!"), infos);
None
}
} else {
None
}
}

pub fn try_get_module(&self, GlobalReference(identifier_span, ref_uuid) : GlobalReference, errors : &ErrorCollector) -> Option<&'linker Module> {
if let Some(uuid) = ref_uuid {
match &self.linker.links.globals[uuid] {
Named::Module(md) => {
Some(md)
},
other => {
let info = other.get_linking_error_location();
let infos = if let Some((file, span)) = info.location {
vec![error_info(span, file, "Defined here")]
} else {
vec![]
};
let name = info.name;
let ident_type = info.named_type;
errors.error_with_info(identifier_span, format!("{ident_type} {name} is not a Module!"), infos);
None
}
pub fn try_get_module(&self, identifier_span : Span, errors : &ErrorCollector) -> Option<&'linker Module> {
let uuid = self.resolve_global(identifier_span, errors)?;
match &self.linker.links.globals[uuid] {
Named::Module(md) => {
Some(md)
},
other => {
let info = other.get_linking_error_location();
let infos = if let Some((file, span)) = info.location {
vec![error_info(span, file, "Defined here")]
} else {
vec![]
};
let name = info.name;
let ident_type = info.named_type;
errors.error_with_info(identifier_span, format!("{ident_type} {name} is not a Module!"), infos);
None
}
} else {
None
}
}
}
10 changes: 2 additions & 8 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,6 @@ struct LeftExpression {
}

impl<'file> ASTParserContext<'file> {
fn add_global_reference(&mut self, name_span : Span) -> usize {
let idx = self.global_references.len();
self.global_references.push(GlobalReference(name_span, None));
idx
}

fn prepare_rollback(&self) -> ASTParserRollbackable {
ASTParserRollbackable{original_global_references_size : self.global_references.len()}
}
Expand Down Expand Up @@ -345,7 +339,7 @@ impl<'file> ASTParserContext<'file> {
LocalOrGlobal::Local(local_idx)
} else {
// todo namespacing and shit
LocalOrGlobal::Global(self.add_global_reference(Span::from(*pos)))
LocalOrGlobal::Global(Span::from(*pos))
};
(Expression::Named(ident_ref), Span::from(*pos))
},
Expand Down Expand Up @@ -446,7 +440,7 @@ impl<'file> ASTParserContext<'file> {
fn try_parse_type(&mut self, token_stream : &mut TokenStream, scope : &LocalVariableContext) -> Option<SpanTypeExpression> {
let first_token = token_stream.eat_is_plain(TOKEN_IDENTIFIER)?;
// todo namespacing and shit
let mut cur_type = (TypeExpression::Named(self.add_global_reference(Span::from(first_token.position))), Span::from(first_token.position)); // TODO add more type info
let mut cur_type = (TypeExpression::Named, Span::from(first_token.position)); // TODO add more type info
while let Some((content, block_span)) = token_stream.eat_is_block(kw("[")) {
let mut array_index_token_stream = TokenStream::new(content, block_span.0, block_span.1);
let expr = self.parse_expression(&mut array_index_token_stream, scope)?;
Expand Down
3 changes: 2 additions & 1 deletion src/tokenizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ pub const ALL_KEYWORDS : [(&'static str, u8); 19] = [

// Extra data is opreator prescedence. Lower number is higher prescedence of operators
// ordered by which to prefer when parsing
pub const ALL_SYMBOLS : [(&'static str, u8); 34] = [
pub const ALL_SYMBOLS : [(&'static str, u8); 35] = [
// 'Meta symbols', for comments. Not actually used in further parsing
("/*", 0),
("//", 0),
("*/", 0),
// Big symbols
("::", 0),
("->", 0),
("..", 1),
("<=", 2), // Start of operators (see is_operator())
Expand Down

0 comments on commit c248875

Please sign in to comment.