From c3db6297d949fadd4134eb4d583559f75bf648ff Mon Sep 17 00:00:00 2001 From: David Mak Date: Mon, 26 Feb 2024 15:11:00 +0800 Subject: [PATCH] core: Add primitive definition-id list So that we have a single ground truth for the definition IDs of primitive types. --- nac3artiq/src/codegen.rs | 4 +- nac3core/src/toplevel/builtins.rs | 29 +++--- nac3core/src/toplevel/composer.rs | 2 +- nac3core/src/toplevel/helper.rs | 88 ++++++++++++++++--- nac3core/src/toplevel/type_annotation.rs | 5 +- .../src/typecheck/type_inferencer/test.rs | 46 +++++----- 6 files changed, 119 insertions(+), 55 deletions(-) diff --git a/nac3artiq/src/codegen.rs b/nac3artiq/src/codegen.rs index 17d2593..1f8feed 100644 --- a/nac3artiq/src/codegen.rs +++ b/nac3artiq/src/codegen.rs @@ -6,7 +6,7 @@ use nac3core::{ CodeGenContext, CodeGenerator, }, symbol_resolver::ValueEnum, - toplevel::{DefinitionId, GenCall}, + toplevel::{DefinitionId, GenCall, helper::PRIMITIVE_DEF_IDS}, typecheck::typedef::{FunSignature, FuncArg, Type, TypeEnum} }; @@ -681,7 +681,7 @@ pub fn attributes_writeback( vars: HashMap::default() }; let args: Vec<_> = values.into_iter().map(|(_, val)| (None, ValueEnum::Dynamic(val))).collect(); - if let Err(e) = rpc_codegen_callback_fn(ctx, None, (&fun, DefinitionId(0)), args, generator) { + if let Err(e) = rpc_codegen_callback_fn(ctx, None, (&fun, PRIMITIVE_DEF_IDS.int32), args, generator) { return Ok(Err(e)); } Ok(Ok(())) diff --git a/nac3core/src/toplevel/builtins.rs b/nac3core/src/toplevel/builtins.rs index 881ea5f..ed52617 100644 --- a/nac3core/src/toplevel/builtins.rs +++ b/nac3core/src/toplevel/builtins.rs @@ -8,6 +8,7 @@ use crate::{ stmt::exn_constructor, }, symbol_resolver::SymbolValue, + toplevel::helper::PRIMITIVE_DEF_IDS, toplevel::numpy::*, }; use inkwell::{ @@ -81,7 +82,7 @@ pub fn get_exn_constructor( methods: vec![("__init__".into(), signature, DefinitionId(cons_id))], ancestors: vec![ TypeAnnotation::CustomClass { id: DefinitionId(class_id), params: Vec::default() }, - TypeAnnotation::CustomClass { id: DefinitionId(7), params: Vec::default() }, + TypeAnnotation::CustomClass { id: PRIMITIVE_DEF_IDS.exception, params: Vec::default() }, ], constructor: Some(signature), resolver: None, @@ -332,49 +333,49 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { }; let top_level_def_list = vec![ Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def( - 0, + PRIMITIVE_DEF_IDS.int32, None, "int32".into(), None, None, ))), Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def( - 1, + PRIMITIVE_DEF_IDS.int64, None, "int64".into(), None, None, ))), Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def( - 2, + PRIMITIVE_DEF_IDS.float, None, "float".into(), None, None, ))), Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def( - 3, + PRIMITIVE_DEF_IDS.bool, None, "bool".into(), None, None, ))), Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def( - 4, + PRIMITIVE_DEF_IDS.none, None, "none".into(), None, None, ))), Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def( - 5, + PRIMITIVE_DEF_IDS.range, None, "range".into(), None, None, ))), Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def( - 6, + PRIMITIVE_DEF_IDS.str, None, "str".into(), None, @@ -382,7 +383,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { ))), Arc::new(RwLock::new(TopLevelDef::Class { name: "Exception".into(), - object_id: DefinitionId(7), + object_id: PRIMITIVE_DEF_IDS.exception, type_vars: Vec::default(), fields: exception_fields, methods: Vec::default(), @@ -392,14 +393,14 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { loc: None, })), Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def( - 8, + PRIMITIVE_DEF_IDS.uint32, None, "uint32".into(), None, None, ))), Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def( - 9, + PRIMITIVE_DEF_IDS.uint64, None, "uint64".into(), None, @@ -408,7 +409,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { Arc::new(RwLock::new({ TopLevelDef::Class { name: "Option".into(), - object_id: DefinitionId(10), + object_id: PRIMITIVE_DEF_IDS.option, type_vars: vec![option_ty_var], fields: vec![], methods: vec![ @@ -417,7 +418,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { ("unwrap".into(), unwrap_ty.0, DefinitionId(13)), ], ancestors: vec![TypeAnnotation::CustomClass { - id: DefinitionId(10), + id: PRIMITIVE_DEF_IDS.option, params: Vec::default(), }], constructor: None, @@ -504,7 +505,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { Arc::new(RwLock::new(TopLevelDef::Class { name: "ndarray".into(), - object_id: DefinitionId(14), + object_id: PRIMITIVE_DEF_IDS.ndarray, type_vars: vec![tvar.0, ndims.0], fields: Vec::default(), methods: Vec::default(), diff --git a/nac3core/src/toplevel/composer.rs b/nac3core/src/toplevel/composer.rs index 77895f8..448e05a 100644 --- a/nac3core/src/toplevel/composer.rs +++ b/nac3core/src/toplevel/composer.rs @@ -221,7 +221,7 @@ impl TopLevelComposer { let constructor_ty = self.unifier.get_dummy_var().0; let mut class_def_ast = ( Arc::new(RwLock::new(Self::make_top_level_class_def( - class_def_id, + DefinitionId(class_def_id), resolver.clone(), fully_qualified_class_name, Some(constructor_ty), diff --git a/nac3core/src/toplevel/helper.rs b/nac3core/src/toplevel/helper.rs index 8e440c1..3d948e2 100644 --- a/nac3core/src/toplevel/helper.rs +++ b/nac3core/src/toplevel/helper.rs @@ -5,6 +5,68 @@ use nac3parser::ast::{Constant, Location}; use super::*; +/// Structure storing [`DefinitionId`] for primitive types. +#[derive(Clone, Copy)] +pub struct PrimitiveDefinitionIds { + pub int32: DefinitionId, + pub int64: DefinitionId, + pub uint32: DefinitionId, + pub uint64: DefinitionId, + pub float: DefinitionId, + pub bool: DefinitionId, + pub none: DefinitionId, + pub range: DefinitionId, + pub str: DefinitionId, + pub exception: DefinitionId, + pub option: DefinitionId, + pub ndarray: DefinitionId, +} + +impl PrimitiveDefinitionIds { + /// Returns all [`DefinitionId`] of primitives as a [`Vec`]. + /// + /// There are no guarantees on ordering of the IDs. + #[must_use] + fn as_vec(&self) -> Vec { + vec![ + self.int32, + self.int64, + self.uint32, + self.uint64, + self.float, + self.bool, + self.none, + self.range, + self.str, + self.exception, + self.option, + self.ndarray, + ] + } + + /// Returns the primitive with the largest [`DefinitionId`]. + #[must_use] + pub fn max_id(&self) -> DefinitionId { + self.as_vec().into_iter().max().unwrap() + } +} + +/// The [definition IDs][DefinitionId] for primitive types. +pub const PRIMITIVE_DEF_IDS: PrimitiveDefinitionIds = PrimitiveDefinitionIds { + int32: DefinitionId(0), + int64: DefinitionId(1), + uint32: DefinitionId(8), + uint64: DefinitionId(9), + float: DefinitionId(2), + bool: DefinitionId(3), + none: DefinitionId(4), + range: DefinitionId(5), + str: DefinitionId(6), + exception: DefinitionId(7), + option: DefinitionId(10), + ndarray: DefinitionId(14), +}; + impl TopLevelDef { pub fn to_string(&self, unifier: &mut Unifier) -> String { match self { @@ -47,42 +109,42 @@ impl TopLevelComposer { pub fn make_primitives(size_t: u32) -> (PrimitiveStore, Unifier) { let mut unifier = Unifier::new(); let int32 = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(0), + obj_id: PRIMITIVE_DEF_IDS.int32, fields: HashMap::new(), params: HashMap::new(), }); let int64 = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(1), + obj_id: PRIMITIVE_DEF_IDS.int64, fields: HashMap::new(), params: HashMap::new(), }); let float = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(2), + obj_id: PRIMITIVE_DEF_IDS.float, fields: HashMap::new(), params: HashMap::new(), }); let bool = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(3), + obj_id: PRIMITIVE_DEF_IDS.bool, fields: HashMap::new(), params: HashMap::new(), }); let none = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(4), + obj_id: PRIMITIVE_DEF_IDS.none, fields: HashMap::new(), params: HashMap::new(), }); let range = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(5), + obj_id: PRIMITIVE_DEF_IDS.range, fields: HashMap::new(), params: HashMap::new(), }); let str = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(6), + obj_id: PRIMITIVE_DEF_IDS.str, fields: HashMap::new(), params: HashMap::new(), }); let exception = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(7), + obj_id: PRIMITIVE_DEF_IDS.exception, fields: vec![ ("__name__".into(), (int32, true)), ("__file__".into(), (str, true)), @@ -99,12 +161,12 @@ impl TopLevelComposer { params: HashMap::new(), }); let uint32 = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(8), + obj_id: PRIMITIVE_DEF_IDS.uint32, fields: HashMap::new(), params: HashMap::new(), }); let uint64 = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(9), + obj_id: PRIMITIVE_DEF_IDS.uint64, fields: HashMap::new(), params: HashMap::new(), }); @@ -121,7 +183,7 @@ impl TopLevelComposer { vars: HashMap::from([(option_type_var.1, option_type_var.0)]), })); let option = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(10), + obj_id: PRIMITIVE_DEF_IDS.option, fields: vec![ ("is_some".into(), (is_some_type_fun_ty, true)), ("is_none".into(), (is_some_type_fun_ty, true)), @@ -155,7 +217,7 @@ impl TopLevelComposer { /// when first registering, the `type_vars`, fields, methods, ancestors are invalid #[must_use] pub fn make_top_level_class_def( - index: usize, + obj_id: DefinitionId, resolver: Option>, name: StrRef, constructor: Option, @@ -163,7 +225,7 @@ impl TopLevelComposer { ) -> TopLevelDef { TopLevelDef::Class { name, - object_id: DefinitionId(index), + object_id: obj_id, type_vars: Vec::default(), fields: Vec::default(), methods: Vec::default(), diff --git a/nac3core/src/toplevel/type_annotation.rs b/nac3core/src/toplevel/type_annotation.rs index 4209a58..3ae2e98 100644 --- a/nac3core/src/toplevel/type_annotation.rs +++ b/nac3core/src/toplevel/type_annotation.rs @@ -1,4 +1,5 @@ use crate::symbol_resolver::SymbolValue; +use crate::toplevel::helper::PRIMITIVE_DEF_IDS; use super::*; use nac3parser::ast::Constant; @@ -93,7 +94,7 @@ pub fn parse_ast_to_type_annotation_kinds( } else if id == &"str".into() { Ok(TypeAnnotation::Primitive(primitives.str)) } else if id == &"Exception".into() { - Ok(TypeAnnotation::CustomClass { id: DefinitionId(7), params: Vec::default() }) + Ok(TypeAnnotation::CustomClass { id: PRIMITIVE_DEF_IDS.exception, params: Vec::default() }) } else if let Ok(obj_id) = resolver.get_identifier_def(*id) { let type_vars = { let def_read = top_level_defs[obj_id.0].try_read(); @@ -491,7 +492,7 @@ pub fn get_type_from_type_annotation_kinds( (*name, (subst_ty, *mutability)) })); let need_subst = !subst.is_empty(); - let ty = if obj_id == &DefinitionId(14) { + let ty = if obj_id == &PRIMITIVE_DEF_IDS.ndarray { assert_eq!(subst.len(), 2); let tv_tys = subst.iter() .sorted_by_key(|(k, _)| *k) diff --git a/nac3core/src/typecheck/type_inferencer/test.rs b/nac3core/src/typecheck/type_inferencer/test.rs index 8de69db..2abffe3 100644 --- a/nac3core/src/typecheck/type_inferencer/test.rs +++ b/nac3core/src/typecheck/type_inferencer/test.rs @@ -3,7 +3,7 @@ use super::*; use crate::{ codegen::CodeGenContext, symbol_resolver::ValueEnum, - toplevel::{DefinitionId, TopLevelDef}, + toplevel::{DefinitionId, helper::PRIMITIVE_DEF_IDS, TopLevelDef}, }; use indoc::indoc; use std::iter::zip; @@ -73,7 +73,7 @@ impl TestEnvironment { let mut unifier = Unifier::new(); let int32 = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(0), + obj_id: PRIMITIVE_DEF_IDS.int32, fields: HashMap::new(), params: HashMap::new(), }); @@ -86,52 +86,52 @@ impl TestEnvironment { fields.insert("__add__".into(), (add_ty, false)); }); let int64 = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(1), + obj_id: PRIMITIVE_DEF_IDS.int64, fields: HashMap::new(), params: HashMap::new(), }); let float = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(2), + obj_id: PRIMITIVE_DEF_IDS.float, fields: HashMap::new(), params: HashMap::new(), }); let bool = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(3), + obj_id: PRIMITIVE_DEF_IDS.bool, fields: HashMap::new(), params: HashMap::new(), }); let none = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(4), + obj_id: PRIMITIVE_DEF_IDS.none, fields: HashMap::new(), params: HashMap::new(), }); let range = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(5), + obj_id: PRIMITIVE_DEF_IDS.range, fields: HashMap::new(), params: HashMap::new(), }); let str = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(6), + obj_id: PRIMITIVE_DEF_IDS.str, fields: HashMap::new(), params: HashMap::new(), }); let exception = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(7), + obj_id: PRIMITIVE_DEF_IDS.exception, fields: HashMap::new(), params: HashMap::new(), }); let uint32 = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(8), + obj_id: PRIMITIVE_DEF_IDS.uint32, fields: HashMap::new(), params: HashMap::new(), }); let uint64 = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(9), + obj_id: PRIMITIVE_DEF_IDS.uint64, fields: HashMap::new(), params: HashMap::new(), }); let option = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(10), + obj_id: PRIMITIVE_DEF_IDS.option, fields: HashMap::new(), params: HashMap::new(), }); @@ -200,7 +200,7 @@ impl TestEnvironment { let mut identifier_mapping = HashMap::new(); let mut top_level_defs: Vec>> = Vec::new(); let int32 = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(0), + obj_id: PRIMITIVE_DEF_IDS.int32, fields: HashMap::new(), params: HashMap::new(), }); @@ -213,52 +213,52 @@ impl TestEnvironment { fields.insert("__add__".into(), (add_ty, false)); }); let int64 = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(1), + obj_id: PRIMITIVE_DEF_IDS.int64, fields: HashMap::new(), params: HashMap::new(), }); let float = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(2), + obj_id: PRIMITIVE_DEF_IDS.float, fields: HashMap::new(), params: HashMap::new(), }); let bool = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(3), + obj_id: PRIMITIVE_DEF_IDS.bool, fields: HashMap::new(), params: HashMap::new(), }); let none = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(4), + obj_id: PRIMITIVE_DEF_IDS.none, fields: HashMap::new(), params: HashMap::new(), }); let range = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(5), + obj_id: PRIMITIVE_DEF_IDS.range, fields: HashMap::new(), params: HashMap::new(), }); let str = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(6), + obj_id: PRIMITIVE_DEF_IDS.str, fields: HashMap::new(), params: HashMap::new(), }); let exception = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(7), + obj_id: PRIMITIVE_DEF_IDS.exception, fields: HashMap::new(), params: HashMap::new(), }); let uint32 = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(8), + obj_id: PRIMITIVE_DEF_IDS.uint32, fields: HashMap::new(), params: HashMap::new(), }); let uint64 = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(9), + obj_id: PRIMITIVE_DEF_IDS.uint64, fields: HashMap::new(), params: HashMap::new(), }); let option = unifier.add_ty(TypeEnum::TObj { - obj_id: DefinitionId(10), + obj_id: PRIMITIVE_DEF_IDS.option, fields: HashMap::new(), params: HashMap::new(), });