From 51bf126a32a02d91feb31a1b00db46066e906e39 Mon Sep 17 00:00:00 2001 From: David Mak Date: Sat, 5 Oct 2024 15:57:51 +0800 Subject: [PATCH] [core] typecheck/type_inferencer: Differentiate global symbols Required for analyzing use of global symbols before global declaration. --- nac3core/src/typecheck/function_check.rs | 12 ++++++---- nac3core/src/typecheck/type_inferencer/mod.rs | 24 +++++++++++++++++-- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/nac3core/src/typecheck/function_check.rs b/nac3core/src/typecheck/function_check.rs index 0f38a341..c4626f2f 100644 --- a/nac3core/src/typecheck/function_check.rs +++ b/nac3core/src/typecheck/function_check.rs @@ -10,7 +10,7 @@ use nac3parser::ast::{ }; use super::{ - type_inferencer::{IdentifierInfo, Inferencer}, + type_inferencer::{DeclarationSource, IdentifierInfo, Inferencer}, typedef::{Type, TypeEnum}, }; use crate::toplevel::helper::PrimDef; @@ -368,7 +368,7 @@ impl<'a> Inferencer<'a> { StmtKind::Global { names, .. } => { for id in names { 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!( "name '{id}' is assigned to before global declaration at {}", stmt.location, @@ -385,8 +385,12 @@ impl<'a> Inferencer<'a> { *id, ) { Ok(_) => { - self.defined_identifiers - .insert(*id, IdentifierInfo { is_global: true }); + self.defined_identifiers.insert( + *id, + IdentifierInfo { + source: DeclarationSource::Global { is_explicit: Some(true) }, + }, + ); } Err(e) => { return Err(HashSet::from([format!( diff --git a/nac3core/src/typecheck/type_inferencer/mod.rs b/nac3core/src/typecheck/type_inferencer/mod.rs index ce2e76d2..dde45d79 100644 --- a/nac3core/src/typecheck/type_inferencer/mod.rs +++ b/nac3core/src/typecheck/type_inferencer/mod.rs @@ -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, + }, +} + /// Information regarding a defined identifier. -#[derive(Clone, Copy, Debug, Default)] +#[derive(Clone, Copy, Debug)] pub struct IdentifierInfo { /// 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 {