use std::{ borrow::BorrowMut, collections::{HashMap, HashSet}, fmt::Debug, iter::FromIterator, sync::Arc, }; use super::codegen::CodeGenContext; use super::typecheck::type_inferencer::PrimitiveStore; use super::typecheck::typedef::{ FunSignature, FuncArg, SharedUnifier, Type, TypeEnum, Unifier, VarMap, }; use crate::{ codegen::CodeGenerator, symbol_resolver::{SymbolResolver, ValueEnum}, typecheck::{ type_inferencer::CodeLocation, typedef::{CallId, TypeVarId}, }, }; use inkwell::values::BasicValueEnum; use itertools::{izip, Itertools}; use nac3parser::ast::{self, Location, Stmt, StrRef}; use parking_lot::RwLock; #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Debug)] pub struct DefinitionId(pub usize); pub mod builtins; pub mod composer; pub mod helper; pub mod numpy; pub mod type_annotation; use composer::*; use type_annotation::*; #[cfg(test)] mod test; type GenCallCallback = dyn for<'ctx, 'a> Fn( &mut CodeGenContext<'ctx, 'a>, Option<(Type, ValueEnum<'ctx>)>, (&FunSignature, DefinitionId), Vec<(Option, ValueEnum<'ctx>)>, &mut dyn CodeGenerator, ) -> Result>, String> + Send + Sync; pub struct GenCall { fp: Box, } impl GenCall { #[must_use] pub fn new(fp: Box) -> GenCall { GenCall { fp } } /// Creates a dummy instance of [`GenCall`], which invokes [`unreachable!()`] with the given /// `reason`. #[must_use] pub fn create_dummy(reason: String) -> GenCall { Self::new(Box::new(move |_, _, _, _, _| unreachable!("{reason}"))) } pub fn run<'ctx>( &self, ctx: &mut CodeGenContext<'ctx, '_>, obj: Option<(Type, ValueEnum<'ctx>)>, fun: (&FunSignature, DefinitionId), args: Vec<(Option, ValueEnum<'ctx>)>, generator: &mut dyn CodeGenerator, ) -> Result>, String> { (self.fp)(ctx, obj, fun, args, generator) } } impl Debug for GenCall { fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Ok(()) } } #[derive(Clone, Debug)] pub struct FunInstance { pub body: Arc>>>, pub calls: Arc>, pub subst: VarMap, pub unifier_id: usize, } #[derive(Debug, Clone)] pub enum TopLevelDef { Class { /// Name for error messages and symbols. name: StrRef, /// Object ID used for [TypeEnum]. object_id: DefinitionId, /// type variables bounded to the class. type_vars: Vec, /// Class fields. /// /// Name and type is mutable. fields: Vec<(StrRef, Type, bool)>, /// Class methods, pointing to the corresponding function definition. methods: Vec<(StrRef, Type, DefinitionId)>, /// Ancestor classes, including itself. ancestors: Vec, /// Symbol resolver of the module defined the class; [None] if it is built-in type. resolver: Option>, /// Constructor type. constructor: Option, /// Definition location. loc: Option, }, Function { /// Prefix for symbol, should be unique globally. name: String, /// Simple name, the same as in method/function definition. simple_name: StrRef, /// Function signature. signature: Type, /// Instantiated type variable IDs. var_id: Vec, /// Function instance to symbol mapping /// /// * Key: String representation of type variable values, sorted by variable ID in ascending /// order, including type variables associated with the class. /// * Value: Function symbol name. instance_to_symbol: HashMap, /// Function instances to annotated AST mapping /// /// * Key: String representation of type variable values, sorted by variable ID in ascending /// order, including type variables associated with the class. Excluding rigid type /// variables. /// /// Rigid type variables that would be substituted when the function is instantiated. instance_to_stmt: HashMap, /// Symbol resolver of the module defined the class. resolver: Option>, /// Custom code generation callback. codegen_callback: Option>, /// Definition location. loc: Option, }, } pub struct TopLevelContext { pub definitions: Arc>>>>, pub unifiers: Arc>>, pub personality_symbol: Option, }