added more accurate type-checking to some of the builtins

This commit is contained in:
Dummi26 2023-04-15 14:41:52 +02:00
parent effdc096a2
commit 65fdc87c01
2 changed files with 95 additions and 5 deletions

View File

@ -332,6 +332,8 @@ impl BuiltinFunction {
if input.len() == 2 { if input.len() == 2 {
// check if the element that should be inserted fits in the list's inner type // check if the element that should be inserted fits in the list's inner type
let (vec, el) = (&input[0], &input[1]); let (vec, el) = (&input[0], &input[1]);
// if vec.is_reference().is_some_and(|v| v) { // unstable
if let Some(true) = vec.is_reference() {
if let Some(t) = vec.get_any() { if let Some(t) = vec.get_any() {
el.fits_in(&t).is_empty() el.fits_in(&t).is_empty()
} else { } else {
@ -340,10 +342,14 @@ impl BuiltinFunction {
} else { } else {
false false
} }
} else {
false
}
} }
Self::Insert => { Self::Insert => {
if input.len() == 3 { if input.len() == 3 {
let (vec, el) = (&input[0], &input[1]); let (vec, el) = (&input[0], &input[1]);
if let Some(true) = vec.is_reference() {
if let Some(t) = vec.get_any() { if let Some(t) = vec.get_any() {
el.fits_in(&t).is_empty() el.fits_in(&t).is_empty()
} else { } else {
@ -352,9 +358,69 @@ impl BuiltinFunction {
} else { } else {
false false
} }
} else {
false
}
}
Self::Pop => {
if input.len() == 1 {
let vec = &input[0];
if let Some(true) = vec.is_reference() {
// TODO! this also returns true for tuples. what should we do for tuples? should pop return (first_val rest_of_tuple) and not take a reference?
if let Some(_) = vec.get_any() {
true
} else {
false
}
} else {
false
}
} else {
false
}
}
Self::Remove => {
if input.len() == 2 {
let (vec, index) = (&input[0], &input[1]);
if let Some(true) = vec.is_reference() {
// TODO! same issue as in pop
if let Some(_) = vec.get_any() {
if index.fits_in(&VSingleType::Int.to()).is_empty() {
true
} else {
false
}
} else {
false
}
} else {
false
}
} else {
false
}
} }
// TODO! finish this // TODO! finish this
Self::Pop | Self::Remove | Self::Get | Self::Len | Self::Substring => true, Self::Get | Self::Len => true,
Self::Substring => {
if input.len() >= 2 && input.len() <= 3 {
let (s, start) = (&input[0], &input[1]);
let index_type = VSingleType::Int.to();
if s.fits_in(&VSingleType::String.to()).is_empty()
&& start.fits_in(&index_type).is_empty()
{
if let Some(end) = input.get(2) {
end.fits_in(&index_type).is_empty()
} else {
true
}
} else {
false
}
} else {
false
}
}
Self::Contains | Self::StartsWith | Self::EndsWith | Self::Regex => { Self::Contains | Self::StartsWith | Self::EndsWith | Self::Regex => {
input.len() == 2 input.len() == 2
&& input && input

View File

@ -41,6 +41,24 @@ impl VType {
} }
Some(out) Some(out)
} }
// returns Some(true) or Some(false) if all types are references or not references. If it is mixed or types is empty, returns None.
pub fn is_reference(&self) -> Option<bool> {
let mut noref = false;
let mut reference = false;
for t in &self.types {
if t.is_reference() {
reference = true;
} else {
noref = true;
}
}
if noref != reference {
Some(reference)
} else {
// either empty (false == false) or mixed (true == true)
None
}
}
} }
impl VSingleType { impl VSingleType {
@ -55,6 +73,12 @@ impl VSingleType {
Self::EnumVariantS(..) => unreachable!(), Self::EnumVariantS(..) => unreachable!(),
} }
} }
pub fn is_reference(&self) -> bool {
match self {
Self::Reference(_) => true,
_ => false,
}
}
} }
impl VType { impl VType {
pub fn get_any(&self) -> Option<VType> { pub fn get_any(&self) -> Option<VType> {