Skip to content

Commit

Permalink
feat: enhance config attribute type inference through the config attr…
Browse files Browse the repository at this point in the history
…ibute type map. (#678)
  • Loading branch information
Peefy authored Aug 23, 2023
1 parent 09cb631 commit 7f51ede
Show file tree
Hide file tree
Showing 16 changed files with 187 additions and 33 deletions.
4 changes: 2 additions & 2 deletions kclvm/api/src/service/ty.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::gpyrpc::{Decorator, KclType};
use indexmap::IndexSet;
use kclvm_runtime::SCHEMA_SETTINGS_ATTR_NAME;
use kclvm_sema::ty::{SchemaType, Type};
use kclvm_sema::ty::{DictType, SchemaType, Type};
use std::collections::HashMap;

/// Convert the kcl sematic type to the kcl protobuf type.
Expand All @@ -12,7 +12,7 @@ pub(crate) fn kcl_ty_to_pb_ty(ty: &Type) -> KclType {
item: Some(Box::new(kcl_ty_to_pb_ty(item_ty))),
..Default::default()
},
kclvm_sema::ty::TypeKind::Dict(key_ty, val_ty) => KclType {
kclvm_sema::ty::TypeKind::Dict(DictType { key_ty, val_ty, .. }) => KclType {
r#type: "dict".to_string(),
key: Some(Box::new(kcl_ty_to_pb_ty(key_ty))),
item: Some(Box::new(kcl_ty_to_pb_ty(val_ty))),
Expand Down
14 changes: 12 additions & 2 deletions kclvm/sema/src/resolver/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::rc::Rc;
use crate::builtin::system_module::{get_system_module_members, UNITS, UNITS_NUMBER_MULTIPLIER};
use crate::builtin::STRING_MEMBER_FUNCTIONS;
use crate::resolver::Resolver;
use crate::ty::{ModuleKind, Type, TypeKind};
use crate::ty::{DictType, ModuleKind, Type, TypeKind};
use kclvm_error::diagnostic::Range;
use kclvm_error::*;

Expand Down Expand Up @@ -46,7 +46,17 @@ impl<'ctx> Resolver<'ctx> {
Some(ty) => (true, Rc::new(ty.clone())),
None => (false, self.any_ty()),
},
TypeKind::Dict(_, val_ty) => (true, Rc::new(val_ty.as_ref().clone())),
TypeKind::Dict(DictType {
key_ty: _,
val_ty,
attrs,
}) => (
true,
attrs
.get(attr)
.map(|attr| attr.ty.clone())
.unwrap_or(Rc::new(val_ty.as_ref().clone())),
),
// union type load attr based the type guard. e.g, a: str|int; if a is str: xxx; if a is int: xxx;
// return sup([self.load_attr_type(t, attr, filename, line, column) for t in obj.types])
TypeKind::Union(_) => (true, self.any_ty()),
Expand Down
21 changes: 16 additions & 5 deletions kclvm/sema/src/resolver/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ use super::{
scope::{ScopeKind, ScopeObject, ScopeObjectKind},
Resolver,
};
use crate::ty::sup;
use crate::ty::SchemaType;
use crate::ty::{sup, DictType};
use crate::ty::{Attr, SchemaType};
use crate::ty::{Type, TypeKind};
use indexmap::IndexMap;
use kclvm_ast::ast;
use kclvm_ast::pos::GetPos;
use kclvm_error::{diagnostic::Range, ErrorKind, Message, Position, Style};
Expand Down Expand Up @@ -73,7 +74,9 @@ impl<'ctx> Resolver<'ctx> {
let obj = obj.clone();
match obj {
Some(obj) => match &obj.ty.kind {
TypeKind::Dict(_, val_ty) => Some(self.new_config_expr_context_item(
TypeKind::Dict(DictType {
key_ty: _, val_ty, ..
}) => Some(self.new_config_expr_context_item(
key_name,
val_ty.clone(),
obj.start.clone(),
Expand Down Expand Up @@ -394,6 +397,7 @@ impl<'ctx> Resolver<'ctx> {
);
let mut key_types: Vec<TypeRef> = vec![];
let mut val_types: Vec<TypeRef> = vec![];
let mut attrs = IndexMap::new();
for item in entries {
let key = &item.node.key;
let value = &item.node.value;
Expand All @@ -417,6 +421,13 @@ impl<'ctx> Resolver<'ctx> {
Rc::new(Type::str_lit(name))
};
self.check_attr_ty(&key_ty, key.get_span_pos());
attrs.insert(
name.to_string(),
Attr {
ty: val_ty.clone(),
range: key.get_span_pos(),
},
);
self.insert_object(
name,
ScopeObject {
Expand Down Expand Up @@ -475,7 +486,7 @@ impl<'ctx> Resolver<'ctx> {
TypeKind::None | TypeKind::Any => {
val_types.push(val_ty.clone());
}
TypeKind::Dict(key_ty, val_ty) => {
TypeKind::Dict(DictType { key_ty, val_ty, .. }) => {
key_types.push(key_ty.clone());
val_types.push(val_ty.clone());
}
Expand Down Expand Up @@ -534,6 +545,6 @@ impl<'ctx> Resolver<'ctx> {
self.leave_scope();
let key_ty = sup(&key_types);
let val_ty = sup(&val_types);
Type::dict_ref(key_ty, val_ty)
Type::dict_ref_with_attrs(key_ty, val_ty, attrs)
}
}
4 changes: 2 additions & 2 deletions kclvm/sema/src/resolver/loop.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::rc::Rc;

use crate::resolver::Resolver;
use crate::ty::{sup, Type, TypeKind};
use crate::ty::{sup, DictType, Type, TypeKind};
use kclvm_ast::ast;
use kclvm_ast::pos::GetPos;
use kclvm_error::diagnostic::Range;
Expand Down Expand Up @@ -53,7 +53,7 @@ impl<'ctx> Resolver<'ctx> {
);
}
}
TypeKind::Dict(key_ty, val_ty) => {
TypeKind::Dict(DictType { key_ty, val_ty, .. }) => {
first_var_ty = sup(&[key_ty.clone(), first_var_ty.clone()]);
self.set_type_to_scope(
first_var_name.as_ref().unwrap(),
Expand Down
12 changes: 8 additions & 4 deletions kclvm/sema/src/resolver/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ use kclvm_error::*;
use std::rc::Rc;

use crate::info::is_private_field;
use crate::ty::{sup, Parameter, Type, TypeInferMethods, TypeKind, RESERVED_TYPE_IDENTIFIERS};
use crate::ty::{
sup, DictType, Parameter, Type, TypeInferMethods, TypeKind, RESERVED_TYPE_IDENTIFIERS,
};

use super::format::VALID_FORMAT_SPEC_SET;
use super::scope::{ScopeKind, ScopeObject, ScopeObjectKind};
Expand Down Expand Up @@ -575,7 +577,9 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> {
}
}
}
TypeKind::Dict(_, val_ty) => {
TypeKind::Dict(DictType {
key_ty: _, val_ty, ..
}) => {
if let Some(index) = &subscript.index {
let index_key_ty = self.expr(index);
if index_key_ty.is_none_or_any() {
Expand Down Expand Up @@ -705,7 +709,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> {
match &ty.kind {
TypeKind::None | TypeKind::Any => (ty.clone(), true),
TypeKind::List(item_ty) => (item_ty.clone(), true),
TypeKind::Dict(key_ty, _) => (key_ty.clone(), true),
TypeKind::Dict(DictType { key_ty, .. }) => (key_ty.clone(), true),
TypeKind::Schema(schema_ty) => (schema_ty.key_ty(), true),
TypeKind::Union(types) => {
let results = types
Expand Down Expand Up @@ -821,7 +825,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> {
}
let mut range = schema_expr.name.get_span_pos();
let ret_ty = match &def_ty.kind {
TypeKind::Dict(_, _) => {
TypeKind::Dict(DictType { .. }) => {
let obj = self.new_config_expr_context_item(
"",
def_ty.clone(),
Expand Down
31 changes: 27 additions & 4 deletions kclvm/sema/src/resolver/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::rc::Rc;

use crate::resolver::Resolver;
use crate::ty::parser::parse_type_str;
use crate::ty::{assignable_to, SchemaType, Type, TypeKind};
use crate::ty::{assignable_to, Attr, DictType, SchemaType, Type, TypeKind};
use indexmap::IndexMap;
use kclvm_ast::ast;
use kclvm_ast::pos::GetPos;
Expand Down Expand Up @@ -123,11 +123,18 @@ impl<'ctx> Resolver<'ctx> {
(TypeKind::List(item_ty), TypeKind::List(expected_item_ty)) => {
self.check_type(item_ty.clone(), expected_item_ty.clone(), range)
}
(TypeKind::Dict(key_ty, val_ty), TypeKind::Dict(expected_key_ty, expected_val_ty)) => {
(
TypeKind::Dict(DictType { key_ty, val_ty, .. }),
TypeKind::Dict(DictType {
key_ty: expected_key_ty,
val_ty: expected_val_ty,
..
}),
) => {
self.check_type(key_ty.clone(), expected_key_ty.clone(), range)
&& self.check_type(val_ty.clone(), expected_val_ty.clone(), range)
}
(TypeKind::Dict(key_ty, val_ty), TypeKind::Schema(schema_ty)) => {
(TypeKind::Dict(DictType { key_ty, val_ty, .. }), TypeKind::Schema(schema_ty)) => {
self.dict_assignable_to_schema(key_ty.clone(), val_ty.clone(), schema_ty, range)
}
(TypeKind::Union(types), _) => types
Expand Down Expand Up @@ -175,9 +182,25 @@ impl<'ctx> Resolver<'ctx> {
TypeKind::List(item_ty) => {
Type::list_ref(self.upgrade_named_ty_with_scope(item_ty.clone(), range))
}
TypeKind::Dict(key_ty, val_ty) => Type::dict_ref(
TypeKind::Dict(DictType {
key_ty,
val_ty,
attrs,
}) => Type::dict_ref_with_attrs(
self.upgrade_named_ty_with_scope(key_ty.clone(), range),
self.upgrade_named_ty_with_scope(val_ty.clone(), range),
attrs
.into_iter()
.map(|(key, attr)| {
(
key.to_string(),
Attr {
ty: self.upgrade_named_ty_with_scope(val_ty.clone(), range),
range: attr.range.clone(),
},
)
})
.collect(),
),
TypeKind::Union(types) => Type::union_ref(
&types
Expand Down
34 changes: 32 additions & 2 deletions kclvm/sema/src/ty/constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ impl Type {
#[inline]
pub fn dict(key_ty: Rc<Type>, val_ty: Rc<Type>) -> Type {
Type {
kind: TypeKind::Dict(key_ty, val_ty),
kind: TypeKind::Dict(DictType {
key_ty,
val_ty,
attrs: IndexMap::new(),
}),
flags: TypeFlags::DICT,
is_type_alias: false,
}
Expand All @@ -43,6 +47,32 @@ impl Type {
pub fn dict_ref(key_ty: Rc<Type>, val_ty: Rc<Type>) -> Rc<Type> {
Rc::new(Self::dict(key_ty, val_ty))
}
/// Construct a dict type with attrs
#[inline]
pub fn dict_with_attrs(
key_ty: TypeRef,
val_ty: TypeRef,
attrs: IndexMap<String, Attr>,
) -> Type {
Type {
kind: TypeKind::Dict(DictType {
key_ty,
val_ty,
attrs,
}),
flags: TypeFlags::DICT,
is_type_alias: false,
}
}
/// Construct a dict type reference with attrs
#[inline]
pub fn dict_ref_with_attrs(
key_ty: TypeRef,
val_ty: TypeRef,
attrs: IndexMap<String, Attr>,
) -> TypeRef {
Rc::new(Self::dict_with_attrs(key_ty, val_ty, attrs))
}
/// Construct a bool literal type.
#[inline]
pub fn bool_lit(val: bool) -> Type {
Expand Down Expand Up @@ -310,7 +340,7 @@ impl Type {
| TypeKind::Str
| TypeKind::StrLit(_)
| TypeKind::List(_)
| TypeKind::Dict(_, _)
| TypeKind::Dict(DictType { .. })
| TypeKind::Union(_)
| TypeKind::Schema(_)
| TypeKind::NumberMultiplier(_)
Expand Down
20 changes: 18 additions & 2 deletions kclvm/sema/src/ty/context.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::HashMap;
use std::rc::Rc;

use super::{sup, Type, TypeFlags, TypeKind};
use super::{sup, Attr, DictType, Type, TypeFlags, TypeKind};
use petgraph::algo::is_cyclic_directed;
use petgraph::graph::{DiGraph, NodeIndex};

Expand Down Expand Up @@ -166,9 +166,25 @@ impl TypeInferMethods for TypeContext {
TypeKind::StrLit(_) => self.builtin_types.str.clone(),
TypeKind::List(item_ty) => Type::list_ref(self.infer_to_variable_type(item_ty.clone())),
// Dict type e.g., {str:1|2} -> {str:int}
TypeKind::Dict(key_ty, val_ty) => Type::dict_ref(
TypeKind::Dict(DictType {
key_ty,
val_ty,
attrs,
}) => Type::dict_ref_with_attrs(
self.infer_to_variable_type(key_ty.clone()),
self.infer_to_variable_type(val_ty.clone()),
attrs
.into_iter()
.map(|(key, attr)| {
(
key.to_string(),
Attr {
ty: self.infer_to_variable_type(attr.ty.clone()),
range: attr.range.clone(),
},
)
})
.collect(),
),
// Union type e.g., 1|2|"s" -> int|str
TypeKind::Union(types) => sup(&types
Expand Down
10 changes: 6 additions & 4 deletions kclvm/sema/src/ty/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ impl Type {
#[inline]
pub fn dict_entry_ty(&self) -> (Rc<Type>, Rc<Type>) {
match &self.kind {
TypeKind::Dict(key_ty, val_ty) => (key_ty.clone(), val_ty.clone()),
TypeKind::Dict(DictType { key_ty, val_ty, .. }) => (key_ty.clone(), val_ty.clone()),
_ => bug!("invalid dict type {}", self.ty_str()),
}
}
/// Downcast ty into the config key type.
#[inline]
pub fn config_key_ty(&self) -> Rc<Type> {
match &self.kind {
TypeKind::Dict(key_ty, _) => key_ty.clone(),
TypeKind::Dict(DictType { key_ty, .. }) => key_ty.clone(),
TypeKind::Schema(schema_ty) => schema_ty.key_ty(),
_ => bug!("invalid config type {}", self.ty_str()),
}
Expand All @@ -30,7 +30,9 @@ impl Type {
#[inline]
pub fn config_val_ty(&self) -> Rc<Type> {
match &self.kind {
TypeKind::Dict(_, val_ty) => val_ty.clone(),
TypeKind::Dict(DictType {
key_ty: _, val_ty, ..
}) => val_ty.clone(),
TypeKind::Schema(schema_ty) => schema_ty.val_ty(),
_ => bug!("invalid config type {}", self.ty_str()),
}
Expand Down Expand Up @@ -79,7 +81,7 @@ impl Type {
}
TypeKind::StrLit(v) => format!("\"{}\"", v.replace('"', "\\\"")),
TypeKind::List(item_ty) => format!("[{}]", item_ty.into_type_annotation_str()),
TypeKind::Dict(key_ty, val_ty) => {
TypeKind::Dict(DictType { key_ty, val_ty, .. }) => {
format!(
"{{{}:{}}}",
key_ty.into_type_annotation_str(),
Expand Down
Loading

0 comments on commit 7f51ede

Please sign in to comment.