nac3core: check type for default parameter

This commit is contained in:
ychenfo 2021-11-23 01:02:42 +08:00
parent 99c103b35b
commit 03cdca606d
2 changed files with 72 additions and 3 deletions

View File

@ -1135,8 +1135,16 @@ impl TopLevelComposer {
ty, ty,
default_value: match default { default_value: match default {
None => None, None => None,
Some(default) => Some(default) => Some({
Some(Self::parse_parameter_default_value(default, resolver)?) let v = Self::parse_parameter_default_value(default, resolver)?;
Self::check_default_param_type(
&v,
&type_annotation,
primitives_store,
unifier
).map_err(|err| format!("{} at {}", err, x.location))?;
v
})
} }
}) })
}) })
@ -1353,7 +1361,12 @@ impl TopLevelComposer {
if name == "self".into() { if name == "self".into() {
return Err(format!("`self` parameter cannot take default value at {}", x.location)); return Err(format!("`self` parameter cannot take default value at {}", x.location));
} }
Some(Self::parse_parameter_default_value(default, class_resolver)?) Some({
let v = Self::parse_parameter_default_value(default, class_resolver)?;
Self::check_default_param_type(&v, &type_ann, primitives, unifier)
.map_err(|err| format!("{} at {}", err, x.location))?;
v
})
} }
} }
}; };

View File

@ -350,6 +350,62 @@ impl TopLevelComposer {
pub fn parse_parameter_default_value(default: &ast::Expr, resolver: &(dyn SymbolResolver + Send + Sync)) -> Result<SymbolValue, String> { pub fn parse_parameter_default_value(default: &ast::Expr, resolver: &(dyn SymbolResolver + Send + Sync)) -> Result<SymbolValue, String> {
parse_parameter_default_value(default, resolver) parse_parameter_default_value(default, resolver)
} }
pub fn check_default_param_type(val: &SymbolValue, ty: &TypeAnnotation, primitive: &PrimitiveStore, unifier: &mut Unifier) -> Result<(), String> {
let res = match val {
SymbolValue::Bool(..) => {
if matches!(ty, TypeAnnotation::Primitive(t) if *t == primitive.bool) {
None
} else {
Some("bool".to_string())
}
}
SymbolValue::Double(..) => {
if matches!(ty, TypeAnnotation::Primitive(t) if *t == primitive.float) {
None
} else {
Some("float".to_string())
}
}
SymbolValue::I32(..) => {
if matches!(ty, TypeAnnotation::Primitive(t) if *t == primitive.int32) {
None
} else {
Some("int32".to_string())
}
}
SymbolValue::I64(..) => {
if matches!(ty, TypeAnnotation::Primitive(t) if *t == primitive.int64) {
None
} else {
Some("int64".to_string())
}
}
SymbolValue::Tuple(elts) => {
if let TypeAnnotation::Tuple(elts_ty) = ty {
for (e, t) in elts.iter().zip(elts_ty.iter()) {
Self::check_default_param_type(e, t, primitive, unifier)?
}
if elts.len() != elts_ty.len() {
Some(format!("tuple of length {}", elts.len()))
} else {
None
}
} else {
Some("tuple".to_string())
}
}
};
if let Some(found) = res {
Err(format!(
"incompatible default parameter type, expect {}, found {}",
ty.stringify(unifier),
found
))
} else {
Ok(())
}
}
} }
pub fn parse_parameter_default_value(default: &ast::Expr, resolver: &(dyn SymbolResolver + Send + Sync)) -> Result<SymbolValue, String> { pub fn parse_parameter_default_value(default: &ast::Expr, resolver: &(dyn SymbolResolver + Send + Sync)) -> Result<SymbolValue, String> {