Some light work on type analysis/analysis context. WIP.

This commit is contained in:
Jesse Brault 2026-10-08 15:52:49 -05:00
parent 3535fed61d
commit 618c3000f1
4 changed files with 62 additions and 30 deletions

View File

@ -31,7 +31,7 @@ pub fn add_primitive_symbols_and_type_infos(ctx: &mut AnalysisContext, global_sc
.try_insert_symbol_in_scope(double_symbol, global_scope_id) .try_insert_symbol_in_scope(double_symbol, global_scope_id)
.unwrap(); .unwrap();
let int_instance_type_info_id = ctx.instance_type(int_symbol_id); let int_instance_type_info_id = *ctx.instance_type(int_symbol_id);
let string_len_symbol = Symbol::Function(FunctionSymbol::new( let string_len_symbol = Symbol::Function(FunctionSymbol::new(
"len".into(), "len".into(),

View File

@ -6,11 +6,31 @@ use crate::diagnostic_factories::symbol_not_found;
use crate::semantic_analysis::diagnostic_helpers::symbol_already_declared; use crate::semantic_analysis::diagnostic_helpers::symbol_already_declared;
use crate::semantic_analysis::scope::{Scope, ScopeId}; use crate::semantic_analysis::scope::{Scope, ScopeId};
use crate::semantic_analysis::symbol::{Symbol, SymbolId}; use crate::semantic_analysis::symbol::{Symbol, SymbolId};
use crate::semantic_analysis::type_info::{ClassTypeInfo, TypeInfo, TypeInfoId}; use crate::semantic_analysis::type_info::{ClassTypeInfo, InstanceTypeInfo, TypeInfo, TypeInfoId};
use crate::source_range::SourceRange; use crate::source_range::SourceRange;
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
#[derive(Debug, Clone)]
struct TypeInfoContainer {
error_type_id: TypeInfoId,
class_symbol_ids_to_type_info_ids: HashMap<SymbolId, TypeInfoId>,
infos: Vec<TypeInfo>,
}
impl Default for TypeInfoContainer {
fn default() -> Self {
let mut infos = vec![];
infos.push(TypeInfo::__Error);
let error_type_id = infos.len() - 1;
Self {
error_type_id,
class_symbol_ids_to_type_info_ids: HashMap::new(),
infos,
}
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct AnalysisState { struct AnalysisState {
fqn_stack: Vec<Rc<str>>, fqn_stack: Vec<Rc<str>>,
@ -19,7 +39,7 @@ struct AnalysisState {
nodes_to_scopes: HashMap<NodeId, ScopeId>, nodes_to_scopes: HashMap<NodeId, ScopeId>,
symbols: Vec<Symbol>, symbols: Vec<Symbol>,
nodes_to_symbols: HashMap<NodeId, SymbolId>, nodes_to_symbols: HashMap<NodeId, SymbolId>,
type_infos: Vec<TypeInfo>, type_infos: Box<TypeInfoContainer>,
symbols_to_type_infos: HashMap<SymbolId, TypeInfoId>, symbols_to_type_infos: HashMap<SymbolId, TypeInfoId>,
nodes_to_type_infos: HashMap<NodeId, TypeInfoId>, nodes_to_type_infos: HashMap<NodeId, TypeInfoId>,
} }
@ -33,7 +53,7 @@ impl Default for AnalysisState {
nodes_to_scopes: HashMap::new(), nodes_to_scopes: HashMap::new(),
symbols: Vec::new(), symbols: Vec::new(),
nodes_to_symbols: HashMap::new(), nodes_to_symbols: HashMap::new(),
type_infos: Vec::new(), type_infos: TypeInfoContainer::default().into(),
symbols_to_type_infos: HashMap::new(), symbols_to_type_infos: HashMap::new(),
nodes_to_type_infos: HashMap::new(), nodes_to_type_infos: HashMap::new(),
} }
@ -73,7 +93,7 @@ impl AnalysisContext {
#[deprecated] #[deprecated]
pub fn type_infos(&self) -> &[TypeInfo] { pub fn type_infos(&self) -> &[TypeInfo] {
&self.state.type_infos &self.state.type_infos.infos
} }
#[deprecated] #[deprecated]
@ -326,8 +346,8 @@ impl AnalysisContext {
#[deprecated] #[deprecated]
pub fn insert_type_info(&mut self, type_info: TypeInfo) -> TypeInfoId { pub fn insert_type_info(&mut self, type_info: TypeInfo) -> TypeInfoId {
self.state.type_infos.push(type_info); self.state.type_infos.infos.push(type_info);
self.state.type_infos.len() - 1 self.state.type_infos.infos.len() - 1
} }
#[deprecated] #[deprecated]
@ -336,8 +356,8 @@ impl AnalysisContext {
type_info: TypeInfo, type_info: TypeInfo,
node_id: NodeId, node_id: NodeId,
) -> TypeInfoId { ) -> TypeInfoId {
self.state.type_infos.push(type_info); self.state.type_infos.infos.push(type_info);
let type_info_id = self.state.type_infos.len() - 1; let type_info_id = self.state.type_infos.infos.len() - 1;
self.state.nodes_to_type_infos.insert(node_id, type_info_id); self.state.nodes_to_type_infos.insert(node_id, type_info_id);
type_info_id type_info_id
} }
@ -374,6 +394,7 @@ impl AnalysisContext {
let type_info_id = self.get_type_info_id_for_node(node_id); let type_info_id = self.get_type_info_id_for_node(node_id);
self.state self.state
.type_infos .type_infos
.infos
.get(type_info_id) .get(type_info_id)
.expect(&format!("invalid type_info_id {}", type_info_id)) .expect(&format!("invalid type_info_id {}", type_info_id))
} }
@ -381,6 +402,7 @@ impl AnalysisContext {
pub fn get_type_info_by_id(&self, type_info_id: TypeInfoId) -> &TypeInfo { pub fn get_type_info_by_id(&self, type_info_id: TypeInfoId) -> &TypeInfo {
self.state self.state
.type_infos .type_infos
.infos
.get(type_info_id) .get(type_info_id)
.expect(&format!("invalid type_info_id {}", type_info_id)) .expect(&format!("invalid type_info_id {}", type_info_id))
} }
@ -440,8 +462,8 @@ impl AnalysisContext {
*type_info_id *type_info_id
} else { } else {
let type_info = TypeInfo::Class(ClassTypeInfo::new(class_symbol_id)); let type_info = TypeInfo::Class(ClassTypeInfo::new(class_symbol_id));
self.state.type_infos.push(type_info); self.state.type_infos.infos.push(type_info);
let type_info_id = self.state.type_infos.len() - 1; let type_info_id = self.state.type_infos.infos.len() - 1;
self.state self.state
.symbols_to_type_infos .symbols_to_type_infos
.insert(class_symbol_id, type_info_id); .insert(class_symbol_id, type_info_id);
@ -453,20 +475,30 @@ impl AnalysisContext {
todo!() todo!()
} }
pub fn int_type(&mut self) -> &TypeInfoId { pub fn error_type(&self) -> &TypeInfoId {
todo!() &self.state.type_infos.error_type_id
} }
pub fn double_type(&mut self) -> &TypeInfoId { pub fn instance_type(&mut self, class_symbol_id: SymbolId) -> &TypeInfoId {
todo!() if !self
.state
.type_infos
.class_symbol_ids_to_type_info_ids
.contains_key(&class_symbol_id)
{
let type_info = TypeInfo::Instance(InstanceTypeInfo::new(class_symbol_id));
self.state.type_infos.infos.push(type_info);
let type_info_id = self.state.type_infos.infos.len() - 1;
self.state
.type_infos
.class_symbol_ids_to_type_info_ids
.insert(class_symbol_id, type_info_id);
} }
self.state
pub fn error_type(&self) -> TypeInfoId { .type_infos
todo!() .class_symbol_ids_to_type_info_ids
} .get(&class_symbol_id)
.unwrap()
pub fn instance_type(&mut self, class_symbol_id: SymbolId) -> TypeInfoId {
todo!()
} }
pub fn instance_type_by_fqn(&self, fqn: &str) -> TypeInfoId { pub fn instance_type_by_fqn(&self, fqn: &str) -> TypeInfoId {
@ -481,6 +513,6 @@ impl AnalysisContext {
self.state self.state
.symbols_to_type_infos .symbols_to_type_infos
.get(&symbol_id) .get(&symbol_id)
.and_then(|type_info_id| self.state.type_infos.get(*type_info_id)) .and_then(|type_info_id| self.state.type_infos.infos.get(*type_info_id))
} }
} }

View File

@ -52,6 +52,6 @@ pub fn negative_op_result(operand: &TypeInfo, ctx: &AnalysisContext) -> TypeInfo
unreachable!() unreachable!()
} }
TypeInfo::Instance(instance_type_info) => instance_type_info.negative_op_result(ctx), TypeInfo::Instance(instance_type_info) => instance_type_info.negative_op_result(ctx),
TypeInfo::__Error => ctx.error_type(), TypeInfo::__Error => *ctx.error_type(),
} }
} }

View File

@ -224,7 +224,7 @@ fn resolve_types_binary_expression(
.with_error_code(BINARY_INCOMPATIBLE_TYPES); .with_error_code(BINARY_INCOMPATIBLE_TYPES);
diagnostics.push(diagnostic); diagnostics.push(diagnostic);
ctx.error_type() *ctx.error_type()
}; };
ctx.associate_node_to_type(binary_expression.node_id(), result_type_info_id); ctx.associate_node_to_type(binary_expression.node_id(), result_type_info_id);
@ -252,7 +252,7 @@ fn resolve_types_negative_expression(
negative_expression.source_range().end(), negative_expression.source_range().end(),
); );
diagnostics.push(diagnostic); diagnostics.push(diagnostic);
ctx.error_type() *ctx.error_type()
}; };
ctx.associate_node_to_type(negative_expression.node_id(), operand_type_info_id); ctx.associate_node_to_type(negative_expression.node_id(), operand_type_info_id);
@ -282,11 +282,11 @@ fn resolve_types_call(
call.source_range().end(), call.source_range().end(),
); );
diagnostics.push(diagnostic); diagnostics.push(diagnostic);
ctx.error_type() *ctx.error_type()
} }
TypeInfo::Class(class_type_info) => { TypeInfo::Class(class_type_info) => {
let symbol = class_type_info.class_symbol_id(); let symbol = class_type_info.class_symbol_id();
ctx.instance_type(symbol) *ctx.instance_type(symbol)
} }
TypeInfo::Constructor(_) => { TypeInfo::Constructor(_) => {
panic!("Cannot check expression type directly on ConstructorTypeInfo"); panic!("Cannot check expression type directly on ConstructorTypeInfo");
@ -295,6 +295,6 @@ fn resolve_types_call(
TypeInfo::Instance(_) => { TypeInfo::Instance(_) => {
unimplemented!("Calling instances of objects not yet supported.") unimplemented!("Calling instances of objects not yet supported.")
} }
TypeInfo::__Error => ctx.error_type(), TypeInfo::__Error => *ctx.error_type(),
} }
} }