Fix several issues with global variables #547
|
@ -10,7 +10,7 @@ use nac3parser::ast::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
type_inferencer::{IdentifierInfo, Inferencer},
|
type_inferencer::{DeclarationSource, IdentifierInfo, Inferencer},
|
||||||
typedef::{Type, TypeEnum},
|
typedef::{Type, TypeEnum},
|
||||||
};
|
};
|
||||||
use crate::toplevel::helper::PrimDef;
|
use crate::toplevel::helper::PrimDef;
|
||||||
|
@ -368,7 +368,7 @@ impl<'a> Inferencer<'a> {
|
||||||
StmtKind::Global { names, .. } => {
|
StmtKind::Global { names, .. } => {
|
||||||
for id in names {
|
for id in names {
|
||||||
if let Some(id_info) = defined_identifiers.get(id) {
|
if let Some(id_info) = defined_identifiers.get(id) {
|
||||||
if !id_info.is_global {
|
if id_info.source == DeclarationSource::Local {
|
||||||
return Err(HashSet::from([format!(
|
return Err(HashSet::from([format!(
|
||||||
"name '{id}' is assigned to before global declaration at {}",
|
"name '{id}' is assigned to before global declaration at {}",
|
||||||
stmt.location,
|
stmt.location,
|
||||||
|
@ -385,8 +385,12 @@ impl<'a> Inferencer<'a> {
|
||||||
*id,
|
*id,
|
||||||
) {
|
) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
self.defined_identifiers
|
self.defined_identifiers.insert(
|
||||||
.insert(*id, IdentifierInfo { is_global: true });
|
*id,
|
||||||
|
IdentifierInfo {
|
||||||
|
source: DeclarationSource::Global { is_explicit: Some(true) },
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(HashSet::from([format!(
|
return Err(HashSet::from([format!(
|
||||||
|
|
|
@ -88,11 +88,31 @@ impl PrimitiveStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The location where an identifier declaration refers to.
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
pub enum DeclarationSource {
|
||||||
|
/// Local scope.
|
||||||
|
Local,
|
||||||
|
|
||||||
|
/// Global scope.
|
||||||
|
Global {
|
||||||
|
/// Whether the identifier is declared by the use of `global` statement. This field is
|
||||||
|
/// [`None`] if the identifier does not refer to a variable.
|
||||||
|
is_explicit: Option<bool>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
/// Information regarding a defined identifier.
|
/// Information regarding a defined identifier.
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct IdentifierInfo {
|
pub struct IdentifierInfo {
|
||||||
/// Whether this identifier refers to a global variable.
|
/// Whether this identifier refers to a global variable.
|
||||||
pub is_global: bool,
|
pub source: DeclarationSource,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for IdentifierInfo {
|
||||||
|
fn default() -> Self {
|
||||||
|
IdentifierInfo { source: DeclarationSource::Local }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IdentifierInfo {
|
impl IdentifierInfo {
|
||||||
|
|
Loading…
Reference in New Issue