From 01f7a31aae6103c4efa0736801686aac8aa741c4 Mon Sep 17 00:00:00 2001 From: ychenfo Date: Tue, 24 Aug 2021 17:43:41 +0800 Subject: [PATCH] put parse ast into type annotation into one function --- nac3core/src/toplevel/mod.rs | 5 +- nac3core/src/toplevel/type_annotation.rs | 281 +++++++----------- .../src/typecheck/type_inferencer/test.rs | 5 +- 3 files changed, 109 insertions(+), 182 deletions(-) diff --git a/nac3core/src/toplevel/mod.rs b/nac3core/src/toplevel/mod.rs index 6656e3d4..f30aaab6 100644 --- a/nac3core/src/toplevel/mod.rs +++ b/nac3core/src/toplevel/mod.rs @@ -3,15 +3,12 @@ use std::ops::{Deref, DerefMut}; use std::{collections::HashMap, collections::HashSet, sync::Arc}; use super::typecheck::type_inferencer::PrimitiveStore; -use super::typecheck::typedef::{SharedUnifier, Type, TypeEnum, Unifier}; +use super::typecheck::typedef::{FunSignature, FuncArg, SharedUnifier, Type, TypeEnum, Unifier}; use crate::symbol_resolver::SymbolResolver; -use crate::typecheck::typedef::{FunSignature, FuncArg}; use itertools::{izip, Itertools}; use parking_lot::{Mutex, RwLock}; use rustpython_parser::ast::{self, Stmt}; - - #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] pub struct DefinitionId(pub usize); diff --git a/nac3core/src/toplevel/type_annotation.rs b/nac3core/src/toplevel/type_annotation.rs index 37251933..d6405da2 100644 --- a/nac3core/src/toplevel/type_annotation.rs +++ b/nac3core/src/toplevel/type_annotation.rs @@ -19,6 +19,7 @@ pub enum TypeAnnotation { TypeVarKind(u32, Type), SelfTypeKind(DefinitionId), } + pub fn parse_ast_to_type_annotation_kinds( resolver: &dyn SymbolResolver, top_level_defs: &[Arc>], @@ -26,31 +27,111 @@ pub fn parse_ast_to_type_annotation_kinds( primitives: &PrimitiveStore, expr: &ast::Expr, ) -> Result { - let results = vec![ - parse_ast_to_concrete_primitive_kind( - resolver, - top_level_defs, - unifier, - primitives, - expr, - ), - parse_ast_to_concretized_custom_class_kind( - resolver, - top_level_defs, - unifier, - primitives, - expr, - ), - parse_ast_to_type_variable_kind(resolver, top_level_defs, unifier, primitives, expr), - parse_ast_to_virtual_kind(resolver, top_level_defs, unifier, primitives, expr), - ]; - let results = results.iter().filter(|x| x.is_ok()).collect_vec(); - if results.len() == 1 { - results[0].clone() - } else { - Err("cannot parsed the type annotation without ambiguity".into()) + match &expr.node { + ast::ExprKind::Name { id, .. } => match id.as_str() { + "int32" => Ok(TypeAnnotation::PrimitiveKind(primitives.int32)), + "int64" => Ok(TypeAnnotation::PrimitiveKind(primitives.int64)), + "float" => Ok(TypeAnnotation::PrimitiveKind(primitives.float)), + "bool" => Ok(TypeAnnotation::PrimitiveKind(primitives.bool)), + "None" => Ok(TypeAnnotation::PrimitiveKind(primitives.none)), + x => { + if let Some(obj_id) = resolver.get_identifier_def(x) { + let def = top_level_defs[obj_id.0].read(); + if let TopLevelDef::Class { .. } = &*def { + Ok(TypeAnnotation::ConcretizedCustomClassKind { + id: obj_id, + params: vec![], + }) + } else { + Err("function cannot be used as a type".into()) + } + } else if let Some(ty) = resolver.get_symbol_type(unifier, primitives, id) { + if let TypeEnum::TVar { id, meta: TypeVarMeta::Generic, range } = + unifier.get_ty(ty).as_ref() + { + // NOTE: always create a new one here + // and later unify if needed + // but record the var_id of the original type var returned by symbol resolver + let range = range.borrow(); + let range = range.as_slice(); + Ok(TypeAnnotation::TypeVarKind( + *id, + unifier.get_fresh_var_with_range(range).0, + )) + } else { + Err("not a type variable identifier".into()) + } + } else { + Err("name cannot be parsed as a type annotation".into()) + } + } + }, + + // TODO: subscript or call + ast::ExprKind::Subscript { value, slice, .. } + if { matches!(&value.node, ast::ExprKind::Name { id, .. } if id == "virtual") } => + { + let def = parse_ast_to_type_annotation_kinds( + resolver, + top_level_defs, + unifier, + primitives, + slice.as_ref(), + )?; + if !matches!(def, TypeAnnotation::ConcretizedCustomClassKind { .. }) { + unreachable!("must be concretized custom class kind in the virtual") + } + Ok(TypeAnnotation::VirtualKind(def.into())) + } + + ast::ExprKind::Subscript { value, slice, .. } => { + if let ast::ExprKind::Name { id, .. } = &value.node { + if vec!["virtual", "Generic"].contains(&id.as_str()) { + return Err("keywords cannot be class name".into()); + } + let obj_id = resolver + .get_identifier_def(id) + .ok_or_else(|| "unknown class name".to_string())?; + let def = top_level_defs[obj_id.0].read(); + if let TopLevelDef::Class { .. } = &*def { + let param_type_infos = if let ast::ExprKind::Tuple { elts, .. } = &slice.node { + elts.iter() + .map(|v| { + parse_ast_to_type_annotation_kinds( + resolver, + top_level_defs, + unifier, + primitives, + v, + ) + }) + .collect::, _>>()? + } else { + vec![parse_ast_to_type_annotation_kinds( + resolver, + top_level_defs, + unifier, + primitives, + slice, + )?] + }; + // NOTE: allow type var in class generic application list + Ok(TypeAnnotation::ConcretizedCustomClassKind { + id: obj_id, + params: param_type_infos, + }) + } else { + Err("function cannot be used as a type".into()) + } + } else { + Err("unsupported expression type for class name".into()) + } + } + + _ => Err("unsupported expression for type annotation".into()), } } + pub fn get_type_from_type_annotation_kinds( top_level_defs: &[Arc>], unifier: &mut Unifier, @@ -154,157 +235,3 @@ pub fn get_type_from_type_annotation_kinds( } } } -fn parse_ast_to_concrete_primitive_kind( - _resolver: &dyn SymbolResolver, - _top_level_defs: &[Arc>], - _unifier: &mut Unifier, - primitives: &PrimitiveStore, - expr: &ast::Expr, -) -> Result { - match &expr.node { - ast::ExprKind::Name { id, .. } => match id.as_str() { - "int32" => Ok(TypeAnnotation::PrimitiveKind(primitives.int32)), - "int64" => Ok(TypeAnnotation::PrimitiveKind(primitives.int64)), - "float" => Ok(TypeAnnotation::PrimitiveKind(primitives.float)), - "bool" => Ok(TypeAnnotation::PrimitiveKind(primitives.bool)), - "None" => Ok(TypeAnnotation::PrimitiveKind(primitives.none)), - _ => Err("not primitive".into()), - }, - _ => Err("not primitive".into()), - } -} -pub fn parse_ast_to_concretized_custom_class_kind( - resolver: &dyn SymbolResolver, - top_level_defs: &[Arc>], - unifier: &mut Unifier, - primitives: &PrimitiveStore, - expr: &ast::Expr, -) -> Result { - match &expr.node { - ast::ExprKind::Name { id, .. } => match id.as_str() { - "int32" | "int64" | "float" | "bool" | "None" => { - Err("expect custom class instead of primitives here".into()) - } - x => { - let obj_id = resolver - .get_identifier_def(x) - .ok_or_else(|| "unknown class name".to_string())?; - let def = top_level_defs[obj_id.0].read(); - if let TopLevelDef::Class { .. } = &*def { - Ok(TypeAnnotation::ConcretizedCustomClassKind { - id: obj_id, - params: vec![], - }) - } else { - Err("function cannot be used as a type".into()) - } - } - }, - ast::ExprKind::Subscript { value, slice, .. } => { - if let ast::ExprKind::Name { id, .. } = &value.node { - if vec!["virtual", "Generic"].contains(&id.as_str()) { - return Err("keywords cannot be class name".into()); - } - let obj_id = resolver - .get_identifier_def(id) - .ok_or_else(|| "unknown class name".to_string())?; - let def = top_level_defs[obj_id.0].read(); - if let TopLevelDef::Class { .. } = &*def { - let param_type_infos = - if let ast::ExprKind::Tuple { elts, .. } = &slice.node { - elts.iter() - .map(|v| { - parse_ast_to_type_annotation_kinds( - resolver, - top_level_defs, - unifier, - primitives, - v, - ) - }) - .collect::, _>>()? - } else { - vec![parse_ast_to_type_annotation_kinds( - resolver, - top_level_defs, - unifier, - primitives, - slice, - )?] - }; - // TODO: allow type var in class generic application list - // if param_type_infos - // .iter() - // .any(|x| matches!(x, TypeAnnotation::TypeVarKind(..))) - // { - // return Err( - // "cannot apply type variable to class generic parameters".into() - // ); - // } - Ok(TypeAnnotation::ConcretizedCustomClassKind { - id: obj_id, - params: param_type_infos, - }) - } else { - Err("function cannot be used as a type".into()) - } - } else { - Err("unsupported expression type for class name".into()) - } - } - _ => Err("unsupported expression type for concretized class".into()), - } -} -pub fn parse_ast_to_virtual_kind( - resolver: &dyn SymbolResolver, - top_level_defs: &[Arc>], - unifier: &mut Unifier, - primitives: &PrimitiveStore, - expr: &ast::Expr, -) -> Result { - match &expr.node { - ast::ExprKind::Subscript { value, slice, .. } - if { matches!(&value.node, ast::ExprKind::Name { id, .. } if id == "virtual") } => - { - let def = parse_ast_to_concretized_custom_class_kind( - resolver, - top_level_defs, - unifier, - primitives, - slice.as_ref(), - )?; - if !matches!(def, TypeAnnotation::ConcretizedCustomClassKind { .. }) { - unreachable!("must be concretized custom class kind in the virtual") - } - Ok(TypeAnnotation::VirtualKind(def.into())) - } - _ => Err("virtual type annotation must be like `virtual[ .. ]`".into()), - } -} -pub fn parse_ast_to_type_variable_kind( - resolver: &dyn SymbolResolver, - _top_level_defs: &[Arc>], - unifier: &mut Unifier, - primitives: &PrimitiveStore, - expr: &ast::Expr, -) -> Result { - if let ast::ExprKind::Name { id, .. } = &expr.node { - let ty = resolver - .get_symbol_type(unifier, primitives, id) - .ok_or_else(|| "unknown type variable name".to_string())?; - if let TypeEnum::TVar { id, meta: TypeVarMeta::Generic, range } = - unifier.get_ty(ty).as_ref() - { - // NOTE: always create a new one here - // and later unify if needed - // but record the var_id of the original type var returned by symbol resolver - let range = range.borrow(); - let range = range.as_slice(); - Ok(TypeAnnotation::TypeVarKind(*id, unifier.get_fresh_var_with_range(range).0)) - } else { - Err("not a type variable identifier".into()) - } - } else { - Err("unsupported expression for type variable".into()) - } -} \ No newline at end of file diff --git a/nac3core/src/typecheck/type_inferencer/test.rs b/nac3core/src/typecheck/type_inferencer/test.rs index 7216a112..531e9bcd 100644 --- a/nac3core/src/typecheck/type_inferencer/test.rs +++ b/nac3core/src/typecheck/type_inferencer/test.rs @@ -1,7 +1,10 @@ use super::super::typedef::*; use super::*; use crate::symbol_resolver::*; -use crate::{location::Location, toplevel::{DefinitionId, TopLevelDef}}; +use crate::{ + location::Location, + toplevel::{DefinitionId, TopLevelDef}, +}; use indoc::indoc; use itertools::zip; use parking_lot::RwLock;