Skip to content
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- The DLS will now correctly report missing template names in 'in each' constructs
- Fixed error where the DLS would fail to match references from within in a template
to symbols defined in parents of objects instantiating the template
- The DLS will now index templates declared inside incorrect contexts (objects, methods, etc.). This avoids internal errors in some cases and allows for slightly-better feedback in broken-syntax contexts.

## 0.9.17
- Fixed linter wrongly throwing an error on space after `defined` keyword
Expand Down
7 changes: 3 additions & 4 deletions src/analysis/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2311,7 +2311,7 @@ impl DeviceAnalysis {
}
}

let base_templates = from_device_and_bases(&root, &bases);
let base_templates = templates_from_device_and_bases(&root, &bases);

trace!("base template names: {:?}", base_templates.iter()
.fold("".to_string(),
Expand Down Expand Up @@ -2489,15 +2489,14 @@ impl DeviceAnalysis {
}
}

pub fn from_device_and_bases<'a>(_device: &'a IsolatedAnalysis,
pub fn templates_from_device_and_bases<'a>(_device: &'a IsolatedAnalysis,
bases: &'a [IsolatedAnalysis])
-> Vec<&'a ObjectDecl<Template>> {
// Need to be sure we get the device toplevel from device here, since
// it has been modified a little from the original isolatedanalysis
let toplevels: Vec<&'a TopLevel> =
bases.iter().map(|ia|&ia.toplevel).collect();
toplevels.iter().flat_map(
|tl|&tl.templates).collect()
toplevels.into_iter().flat_map(|tl|tl.gather_templates()).collect()
}

fn bind_method_implementations(method_symbols: &mut HashMap<ZeroSpan, HashMap<StructureKey, SymbolRef>>) {
Expand Down
5 changes: 5 additions & 0 deletions src/analysis/structure/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,11 @@ impl ScopeContainer for Statements {
fn scopes(&self) -> Vec<&dyn Scope> {
let mut scopes = self.statements.scopes();
scopes.append(&mut self.ineachs.to_scopes());
for obj in &self.statements {
if let DMLStatement::Object(DMLObject::Template(template)) = obj {
scopes.push(template as &dyn Scope);
}
}
scopes
}
}
Expand Down
75 changes: 54 additions & 21 deletions src/analysis/structure/toplevel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,7 @@ use std::path::PathBuf;

use log::trace;

use crate::analysis::structure::objects::{Bitorder, CBlock, CompositeObject,
CompObjectKind, Constant, Device,
DMLObject, DMLStatement, Error,
make_statements, Hook,
Loggroup, Import, InEach,
Instantiation, Method, MethodModifier,
Export, Parameter, Statements,
Template, Typedef,
Variable, Version, ToStructure};
use crate::analysis::structure::objects::{Bitorder, CBlock, CompObjectKind, CompositeObject, Constant, DMLObject, DMLStatement, Device, Error, Export, Hook, Import, InEach, Instantiation, Loggroup, Method, MethodModifier, Parameter, Statements, Template, ToStructure, Typedef, Variable, Version, make_statements};
use crate::analysis::structure::expressions::{Expression};
use crate::analysis::FileSpec;
use crate::analysis::parsing::tree::{ZeroRange, ZeroSpan, TreeElement};
Expand Down Expand Up @@ -240,6 +232,9 @@ pub struct StatementSpec {
pub exports: Vec<ObjectDecl<Export>>,
pub hooks: Vec<ObjectDecl<Hook>>,
pub instantiations: Vec<ObjectDecl<Instantiation>>,
// Templates are actually forbidden except in toplevel, but we keep this here
// in order to be able to track them anyway
pub templates: Vec<ObjectDecl<Template>>,
// It is a bit strange to keep this here, but we need this
// in the contexts where we only have a spec. It is empty everywhere
// except toplevel
Expand All @@ -266,11 +261,27 @@ impl ScopeContainer for StatementSpec {
let mut scopes = self.methods.to_scopes();
scopes.append(&mut self.objects.to_scopes());
scopes.append(&mut self.ineachs.to_scopes());
scopes.append(&mut self.templates.to_scopes());
scopes
}
}

impl StatementSpec {
pub fn gather_templates(&self) -> Vec<&ObjectDecl<Template>> {
let mut templates = vec![];
for obj in &self.objects {
templates.append(&mut obj.spec.gather_templates());
}
for obj in &self.ineachs {
templates.append(&mut obj.spec.gather_templates());
}
for obj in &self.templates {
templates.append(&mut obj.spec.gather_templates());
}
templates.extend(&self.templates);
templates
}

pub fn empty() -> StatementSpec {
StatementSpec {
objects: vec![],
Expand All @@ -285,6 +296,7 @@ impl StatementSpec {
ineachs: vec![],
exports: vec![],
imports: vec![],
templates: vec![],
}
}
pub fn consume(mut self,
Expand All @@ -298,6 +310,7 @@ impl StatementSpec {
ineachs: &mut Vec<ObjectDecl<InEach>>,
exports: &mut Vec<ObjectDecl<Export>>,
errors: &mut Vec<ObjectDecl<Error>>,
templates: &mut Vec<ObjectDecl<Template>>,
imports: &mut Vec<ObjectDecl<Import>>) {
objects.append(&mut self.objects);
constants.append(&mut self.constants);
Expand All @@ -310,6 +323,7 @@ impl StatementSpec {
exports.append(&mut self.exports);
errors.append(&mut self.errors);
imports.append(&mut self.imports);
templates.append(&mut self.templates);
}
}

Expand All @@ -331,6 +345,7 @@ fn flatten_hashif_branch(context: StatementContext,
let mut exports = vec![];
let mut hooks = vec![];
let mut errors = vec![];
let mut templates = vec![];
for inst in &stmnts.instantiations {
instantiations.push(ObjectDecl::depending_on_context(
inst, context, &conds));
Expand Down Expand Up @@ -391,13 +406,27 @@ fn flatten_hashif_branch(context: StatementContext,
"Extern declaration not allowed in {}",
context),
}),
DMLObject::Template(tmpl) =>
DMLObject::Template(tmpl) => {
// Invalid place to declare a template, but track it anyway
// to allow better feedback while editing
let subspec = flatten_hashif_branch(
StatementContext::Template,
&tmpl.statements,
vec![],
report);
templates.push(
ObjectDecl {
cond: ExistCondition::Always,
obj: tmpl.clone(),
spec: subspec,
});
report.push(LocalDMLError {
range: tmpl.object.name.span.range,
description: format!(
"Template declaration not allowed in {}",
context),
}),
})
},
DMLObject::Header(block) =>
report.push(LocalDMLError {
range: block.span.range,
Expand Down Expand Up @@ -512,6 +541,7 @@ fn flatten_hashif_branch(context: StatementContext,
&mut ineachs,
&mut exports,
&mut errors,
&mut templates,
&mut vec![]);
falsebranchspec.consume(&mut objects,
&mut sessions,
Expand All @@ -523,6 +553,7 @@ fn flatten_hashif_branch(context: StatementContext,
&mut ineachs,
&mut exports,
&mut errors,
&mut templates,
&mut vec![]);
},
}
Expand All @@ -539,6 +570,7 @@ fn flatten_hashif_branch(context: StatementContext,
hooks,
instantiations,
errors,
templates,
imports: vec![],
}
}
Expand All @@ -557,7 +589,6 @@ pub struct TopLevel {
pub cblocks: Vec<CBlock>,
pub externs: Vec<Variable>,
pub typedefs: Vec<Typedef>,
pub templates: Vec<ObjectDecl<Template>>,
pub references: Vec<Reference>,
pub spec: StatementSpec,
// The philosophy for duplicate templates is to track them,
Expand Down Expand Up @@ -592,14 +623,10 @@ impl Scope for TopLevel {
&self.references
}
fn defined_scopes(&self) -> Vec<&dyn Scope> {
let mut scopes = self.spec.scopes();
scopes.append(&mut self.templates.to_scopes());
scopes
self.spec.scopes()
}
fn defined_symbols(&self) -> Vec<&dyn StructureSymbol> {
let mut symbols = self.spec.symbols();
symbols.append(&mut self.templates.to_symbols());
symbols
self.spec.symbols()
}
}

Expand All @@ -615,7 +642,7 @@ impl fmt::Display for TopLevel {
writeln!(f, "\tdevice: {}", dev.name.val)?;
}
write!(f, "\ttemplates: [")?;
for template in &self.templates {
for template in &self.spec.templates {
write!(f, "{}, ", template.obj.object.name.val)?;
}
writeln!(f, "]")?;
Expand All @@ -626,6 +653,10 @@ impl fmt::Display for TopLevel {

// Rudimentary checks for toplevel only
impl TopLevel {
pub fn gather_templates(&self) -> Vec<&ObjectDecl<Template>> {
self.spec.gather_templates()
}

pub fn from_ast(ast: &structure::TopAst,
report: &mut Vec<LocalDMLError>,
filespec: FileSpec<'_>)
Expand Down Expand Up @@ -794,6 +825,7 @@ impl TopLevel {
&mut ineachs,
&mut exports,
&mut errors,
&mut templates,
&mut vec![]);
falsebranchspec.consume(&mut objects,
&mut sessions,
Expand All @@ -805,14 +837,16 @@ impl TopLevel {
&mut ineachs,
&mut exports,
&mut errors,
&mut templates,
&mut vec![]);
},
}
}

let spec = StatementSpec {
objects, instantiations, ineachs, errors, imports,
saveds, sessions, params, constants, methods, exports, hooks
saveds, sessions, params, constants, methods, exports, hooks,
templates,
};
let mut references = vec![];
ast.references(&mut references, filespec);
Expand All @@ -834,7 +868,6 @@ impl TopLevel {
externs,
typedefs,
bitorder,
templates,
loggroups,
spec,
references,
Expand Down