Skip to content

Commit

Permalink
feat: enhance config to schema type check on union expr
Browse files Browse the repository at this point in the history
Signed-off-by: peefy <[email protected]>
  • Loading branch information
Peefy committed Aug 13, 2024
1 parent dcbd9d9 commit a799a1f
Show file tree
Hide file tree
Showing 16 changed files with 178 additions and 119 deletions.
22 changes: 17 additions & 5 deletions kclvm/sema/src/resolver/calculation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ use std::sync::Arc;

use crate::resolver::Resolver;
use crate::ty::{
has_any_type, is_upper_bound, sup, Type, TypeInferMethods, TypeRef, ZERO_LIT_TYPES,
has_any_type, is_upper_bound, sup, Type, TypeInferMethods, TypeKind, TypeRef, ZERO_LIT_TYPES,
};
use indexmap::IndexMap;
use kclvm_ast::ast;
use kclvm_error::diagnostic::Range;

Expand Down Expand Up @@ -162,12 +163,23 @@ impl<'ctx> Resolver<'ctx> {
true,
Type::list_ref(sup(&[t1.list_item_ty(), t2.list_item_ty()])),
)
} else if t1.is_dict() && t2.is_dict() {
let (t1_key_ty, t1_val_ty) = t1.dict_entry_ty();
let (t2_key_ty, t2_val_ty) = t2.dict_entry_ty();
} else if let (TypeKind::Dict(t1_dict_ty), TypeKind::Dict(t2_dict_ty)) =
(&t1.kind, &t2.kind)
{
let mut attrs = IndexMap::new();
for (k, v) in &t1_dict_ty.attrs {
attrs.insert(k.to_string(), v.clone());
}
for (k, v) in &t2_dict_ty.attrs {
attrs.insert(k.to_string(), v.clone());
}
(
true,
Type::dict_ref(sup(&[t1_key_ty, t2_key_ty]), sup(&[t1_val_ty, t2_val_ty])),
Arc::new(Type::dict_with_attrs(
sup(&[t1_dict_ty.key_ty.clone(), t2_dict_ty.key_ty.clone()]),
sup(&[t1_dict_ty.val_ty.clone(), t2_dict_ty.val_ty.clone()]),
attrs,
)),
)
} else if t1.is_schema() && (t2.is_schema() || t2.is_dict()) {
(true, t1)
Expand Down
67 changes: 46 additions & 21 deletions kclvm/sema/src/resolver/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,34 +297,59 @@ impl<'ctx> Resolver<'ctx> {
}
_ => val_ty,
};

if !self.check_type(val_ty.clone(), index_signature.val_ty.clone(), range) {
self.handler.add_type_error(
&format!(
"expected schema index signature value type {}, got {}",
index_signature.val_ty.ty_str(),
val_ty.ty_str()
),
range.clone(),
);
}

if index_signature.any_other {
return self.check_type(key_ty, index_signature.key_ty.clone(), range)
&& self.check_type(val_ty, index_signature.val_ty.clone(), range);
if dict_ty.attrs.is_empty() {
if !self.check_type(val_ty.clone(), index_signature.val_ty.clone(), range) {
self.handler.add_type_error(
&format!(
"expected schema index signature value type {}, got {}",
index_signature.val_ty.ty_str(),
val_ty.ty_str()
),
range.clone(),
);
}
} else {
for (name, attr) in &dict_ty.attrs {
if index_signature.any_other {
if let Some(attr_obj) = schema_ty.attrs.get(name) {
self.must_assignable_to(
attr.ty.clone(),
attr_obj.ty.clone(),
range.clone(),
Some(attr_obj.range.clone()),
);
} else {
self.must_assignable_to(
attr.ty.clone(),
index_signature.val_ty.clone(),
attr.range.clone(),
None,
);
}
} else {
self.must_assignable_to(
attr.ty.clone(),
index_signature.val_ty.clone(),
attr.range.clone(),
None,
);
}
}
}
true
} else {
// When assigning a dict type to an instance of a schema type,
// check whether the type of key value pair in dict matches the attribute type in the schema.
if let TypeKind::StrLit(key_name) = &key_ty.kind {
if let Some(attr_obj) = schema_ty.attrs.get(key_name) {
self.must_assignable_to(
val_ty.clone(),
attr_obj.ty.clone(),
range.clone(),
Some(attr_obj.range.clone()),
);
if let Some(attr) = dict_ty.attrs.get(key_name) {
self.must_assignable_to(
attr.ty.clone(),
attr_obj.ty.clone(),
range.clone(),
Some(attr_obj.range.clone()),
);
}
return true;
}
}
Expand Down
52 changes: 0 additions & 52 deletions test/grammar/lambda/type_annotation/schema/invalid_1/stderr.golden
Original file line number Diff line number Diff line change
Expand Up @@ -17,55 +17,3 @@ error[E2G22]: TypeError
10 | hello: "world"
| ^ expected int, got str(world)
|

--> ${CWD}/main.k:7:5
|
7 | {
| ^ variable is defined here, its type is int, but got str(world)
|

error[E2G22]: TypeError
--> ${CWD}/main.k:15:5
|
15 | version: 1
| ^ expected str, got int(1)
|

--> ${CWD}/main.k:3:5
|
3 | version: str
| ^ variable is defined here, its type is str, but got int(1)
|

error[E2G22]: TypeError
--> ${CWD}/main.k:16:5
|
16 | hello: "world"
| ^ expected int, got str(world)
|

--> ${CWD}/main.k:14:20
|
14 | v = providerFamily({
| ^ variable is defined here, its type is int, but got str(world)
|

error[E2G22]: TypeError
--> ${CWD}/main.k:14:20
|
14 | v = providerFamily({
| ^ expected schema index signature value type int, got str(world)
|

error[E2G22]: TypeError
--> ${CWD}/main.k:14:20
|
14 | v = providerFamily({
| ^ expected ProviderFamily, got {str(version) | str(hello):int(1) | str(world)}
|

--> ${CWD}/main.k:6:25
|
6 | providerFamily = lambda family: ProviderFamily -> ProviderFamily {
| ^ variable is defined here, its type is ProviderFamily, but got {str(version) | str(hello):int(1) | str(world)}
|
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,3 @@ error[E2G22]: TypeError
6 | name: Name
| ^ variable is defined here, its type is int, but got str(aa)
|
error[E2G22]: TypeError
--> ${CWD}/main.k:9:5
|
9 | name: {
| ^ expected schema index signature value type int, got str(aa)
|
error[E2G22]: TypeError
--> ${CWD}/main.k:9:5
|
9 | name: {
| ^ expected Name, got {str(classID):str(aa)}
|
--> ${CWD}/main.k:6:5
|
6 | name: Name
| ^ variable is defined here, its type is Name, but got {str(classID):str(aa)}
|
22 changes: 0 additions & 22 deletions test/grammar/schema/type/config_expr_type_fail_1/stderr.golden
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,6 @@ error[E2G22]: TypeError
|
--> ${CWD}/main.k:2:5
|
2 | name: str = "Kiki"
| ^ variable is defined here, its type is str, but got int(123)
|
error[E2G22]: TypeError
--> ${CWD}/main.k:12:10
|
12 | name.name0.name = 123
| ^ expected str, got int(123)
|
--> ${CWD}/main.k:2:5
|
2 | name: str = "Kiki"
| ^ variable is defined here, its type is str, but got int(123)
|
error[E2G22]: TypeError
--> ${CWD}/main.k:12:5
|
12 | name.name0.name = 123
| ^ expected str, got int(123)
|
--> ${CWD}/main.k:2:5
|
2 | name: str = "Kiki"
| ^ variable is defined here, its type is str, but got int(123)
|
4 changes: 2 additions & 2 deletions test/grammar/schema/type/type_fail_24/stderr.golden
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ error[E2G22]: TypeError
--> ${CWD}/main.k:4:5
|
4 | name: {
| ^ expected [Container], got {str(image) | str(name):str(image) | str(name)}
| ^ expected [Container], got {str:str}
|
--> ${CWD}/pkg/person.k:3:5
|
3 | spec: [Container]
| ^ variable is defined here, its type is [Container], but got {str(image) | str(name):str(image) | str(name)}
| ^ variable is defined here, its type is [Container], but got {str:str}
|
14 changes: 14 additions & 0 deletions test/grammar/types/union_expr/union_expr_0/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
schema Container:
name: str
image: str
volumeMounts: [{str:}]

config = {
image = "test/test-container:test-cluster"
volumeMounts = [{
name = "config"
mountPath = "/app/config"
}]
}

expected: Container = config | {name = "test-repo/test-image:test-tag"}
11 changes: 11 additions & 0 deletions test/grammar/types/union_expr/union_expr_0/stdout.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
config:
image: test/test-container:test-cluster
volumeMounts:
- name: config
mountPath: /app/config
expected:
name: test-repo/test-image:test-tag
image: test/test-container:test-cluster
volumeMounts:
- name: config
mountPath: /app/config
16 changes: 16 additions & 0 deletions test/grammar/types/union_expr/union_expr_1/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
schema Container:
name: str
image: str
volumeMounts: [{str:}]

schema Config:
_config = {
image = "test/test-container:test-cluster"
volumeMounts = [{
name = "config"
mountPath = "/app/config"
}]
}
expected: Container = _config | {name = "test-repo/test-image:test-tag"}

config = Config {}
7 changes: 7 additions & 0 deletions test/grammar/types/union_expr/union_expr_1/stdout.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
config:
expected:
name: test-repo/test-image:test-tag
image: test/test-container:test-cluster
volumeMounts:
- name: config
mountPath: /app/config
14 changes: 14 additions & 0 deletions test/grammar/types/union_expr/union_expr_fail_0/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
schema Container:
name: str
image: str
volumeMounts: [{str:}]

config = {
image = "test/test-container:test-cluster"
volumeMounts = [{
name = "config"
mountPath = "/app/config"
}]
}

expected: Container = config | {name = 1}
6 changes: 6 additions & 0 deletions test/grammar/types/union_expr/union_expr_fail_0/stderr.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
error[E2G22]: TypeError
--> ${CWD}/main.k:14:33
|
14 | expected: Container = config | {name = 1}
| ^ expected str, got int(1)
|
16 changes: 16 additions & 0 deletions test/grammar/types/union_expr/union_expr_fail_1/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
schema Container:
name: str
image: str
volumeMounts: [{str:}]

schema Config:
_config = {
image = "test/test-container:test-cluster"
volumeMounts = [{
name = "config"
mountPath = "/app/config"
}]
}
expected: Container = _config | {name = 1}

config = Config {}
6 changes: 6 additions & 0 deletions test/grammar/types/union_expr/union_expr_fail_1/stderr.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
error[E2G22]: TypeError
--> ${CWD}/main.k:14:38
|
14 | expected: Container = _config | {name = 1}
| ^ expected str, got int(1)
|
17 changes: 17 additions & 0 deletions test/grammar/types/union_expr/union_expr_fail_2/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
schema Container:
name: str
image: str
volumeMounts: [{str:}]

schema Config:
_config = {
name = 1
image = "test/test-container:test-cluster"
volumeMounts = [{
name = "config"
mountPath = "/app/config"
}]
}
expected: Container = _config | {}

config = Config {}
6 changes: 6 additions & 0 deletions test/grammar/types/union_expr/union_expr_fail_2/stderr.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
error[E3M38]: EvaluationError
--> ${CWD}/main.k:2:1
|
2 | name: str
| expect str, got int
|

0 comments on commit a799a1f

Please sign in to comment.