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)
.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(
"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::scope::{Scope, ScopeId};
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 std::collections::HashMap;
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)]
struct AnalysisState {
fqn_stack: Vec<Rc<str>>,
@ -19,7 +39,7 @@ struct AnalysisState {
nodes_to_scopes: HashMap<NodeId, ScopeId>,
symbols: Vec<Symbol>,
nodes_to_symbols: HashMap<NodeId, SymbolId>,
type_infos: Vec<TypeInfo>,
type_infos: Box<TypeInfoContainer>,
symbols_to_type_infos: HashMap<SymbolId, TypeInfoId>,
nodes_to_type_infos: HashMap<NodeId, TypeInfoId>,
}
@ -33,7 +53,7 @@ impl Default for AnalysisState {
nodes_to_scopes: HashMap::new(),
symbols: Vec::new(),
nodes_to_symbols: HashMap::new(),
type_infos: Vec::new(),
type_infos: TypeInfoContainer::default().into(),
symbols_to_type_infos: HashMap::new(),
nodes_to_type_infos: HashMap::new(),
}
@ -73,7 +93,7 @@ impl AnalysisContext {
#[deprecated]
pub fn type_infos(&self) -> &[TypeInfo] {
&self.state.type_infos
&self.state.type_infos.infos
}
#[deprecated]
@ -326,8 +346,8 @@ impl AnalysisContext {
#[deprecated]
pub fn insert_type_info(&mut self, type_info: TypeInfo) -> TypeInfoId {
self.state.type_infos.push(type_info);
self.state.type_infos.len() - 1
self.state.type_infos.infos.push(type_info);
self.state.type_infos.infos.len() - 1
}
#[deprecated]
@ -336,8 +356,8 @@ impl AnalysisContext {
type_info: TypeInfo,
node_id: NodeId,
) -> TypeInfoId {
self.state.type_infos.push(type_info);
let type_info_id = self.state.type_infos.len() - 1;
self.state.type_infos.infos.push(type_info);
let type_info_id = self.state.type_infos.infos.len() - 1;
self.state.nodes_to_type_infos.insert(node_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);
self.state
.type_infos
.infos
.get(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 {
self.state
.type_infos
.infos
.get(type_info_id)
.expect(&format!("invalid type_info_id {}", type_info_id))
}
@ -440,8 +462,8 @@ impl AnalysisContext {
*type_info_id
} else {
let type_info = TypeInfo::Class(ClassTypeInfo::new(class_symbol_id));
self.state.type_infos.push(type_info);
let type_info_id = self.state.type_infos.len() - 1;
self.state.type_infos.infos.push(type_info);
let type_info_id = self.state.type_infos.infos.len() - 1;
self.state
.symbols_to_type_infos
.insert(class_symbol_id, type_info_id);
@ -453,20 +475,30 @@ impl AnalysisContext {
todo!()
}
pub fn int_type(&mut self) -> &TypeInfoId {
todo!()
pub fn error_type(&self) -> &TypeInfoId {
&self.state.type_infos.error_type_id
}
pub fn double_type(&mut self) -> &TypeInfoId {
todo!()
pub fn instance_type(&mut self, class_symbol_id: SymbolId) -> &TypeInfoId {
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);
}
pub fn error_type(&self) -> TypeInfoId {
todo!()
}
pub fn instance_type(&mut self, class_symbol_id: SymbolId) -> TypeInfoId {
todo!()
self.state
.type_infos
.class_symbol_ids_to_type_info_ids
.get(&class_symbol_id)
.unwrap()
}
pub fn instance_type_by_fqn(&self, fqn: &str) -> TypeInfoId {
@ -481,6 +513,6 @@ impl AnalysisContext {
self.state
.symbols_to_type_infos
.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!()
}
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);
diagnostics.push(diagnostic);
ctx.error_type()
*ctx.error_type()
};
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(),
);
diagnostics.push(diagnostic);
ctx.error_type()
*ctx.error_type()
};
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(),
);
diagnostics.push(diagnostic);
ctx.error_type()
*ctx.error_type()
}
TypeInfo::Class(class_type_info) => {
let symbol = class_type_info.class_symbol_id();
ctx.instance_type(symbol)
*ctx.instance_type(symbol)
}
TypeInfo::Constructor(_) => {
panic!("Cannot check expression type directly on ConstructorTypeInfo");
@ -295,6 +295,6 @@ fn resolve_types_call(
TypeInfo::Instance(_) => {
unimplemented!("Calling instances of objects not yet supported.")
}
TypeInfo::__Error => ctx.error_type(),
TypeInfo::__Error => *ctx.error_type(),
}
}