references can now be of type &(int/float): two types, one reference.

This commit is contained in:
mark 2023-06-12 18:18:45 +02:00
parent 217a527c01
commit d94f727eaa
9 changed files with 56 additions and 59 deletions

2
mers/Cargo.lock generated
View File

@ -647,7 +647,7 @@ dependencies = [
[[package]] [[package]]
name = "mers" name = "mers"
version = "0.2.0" version = "0.2.1"
dependencies = [ dependencies = [
"colorize", "colorize",
"edit", "edit",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "mers" name = "mers"
version = "0.2.0" version = "0.2.1"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -486,7 +486,7 @@ impl BuiltinFunction {
&VType { &VType {
types: vec![ types: vec![
VSingleType::String, VSingleType::String,
VSingleType::Reference(Box::new(VSingleType::String)), VSingleType::Reference(VSingleType::String.to()),
], ],
}, },
info, info,

View File

@ -349,16 +349,7 @@ impl RStatementEnum {
.into(), .into(),
Self::Variable(t, is_ref) => { Self::Variable(t, is_ref) => {
if *is_ref { if *is_ref {
VType { VSingleType::Reference(t.lock().unwrap().1.clone()).to()
types: t
.lock()
.unwrap()
.1
.types
.iter()
.map(|t| VSingleType::Reference(Box::new(t.clone())))
.collect(),
}
} else { } else {
t.lock().unwrap().1.clone() t.lock().unwrap().1.clone()
} }

View File

@ -312,7 +312,7 @@ pub fn stype(t: &mut VSingleType, ginfo: &mut GlobalScriptInfo) -> Result<(), To
} }
} }
VSingleType::List(t) => stypes(t, ginfo)?, VSingleType::List(t) => stypes(t, ginfo)?,
VSingleType::Reference(t) => stype(t, ginfo)?, VSingleType::Reference(t) => stypes(t, ginfo)?,
VSingleType::Thread(t) => stypes(t, ginfo)?, VSingleType::Thread(t) => stypes(t, ginfo)?,
VSingleType::EnumVariantS(e, v) => { VSingleType::EnumVariantS(e, v) => {
*t = VSingleType::EnumVariant( *t = VSingleType::EnumVariant(

View File

@ -318,7 +318,7 @@ impl VDataEnum {
Self::List(t, _) => VSingleType::List(t.clone()), Self::List(t, _) => VSingleType::List(t.clone()),
Self::Function(f) => VSingleType::Function(f.out_map.clone()), Self::Function(f) => VSingleType::Function(f.out_map.clone()),
Self::Thread(_, o) => VSingleType::Thread(o.clone()), Self::Thread(_, o) => VSingleType::Thread(o.clone()),
Self::Reference(r) => VSingleType::Reference(Box::new(r.out_single())), Self::Reference(r) => VSingleType::Reference(r.out()),
Self::EnumVariant(e, v) => VSingleType::EnumVariant(*e, v.out_single().to()), Self::EnumVariant(e, v) => VSingleType::EnumVariant(*e, v.out_single().to()),
} }
} }

View File

@ -28,7 +28,7 @@ pub enum VSingleType {
List(VType), List(VType),
Function(Vec<(Vec<VType>, VType)>), Function(Vec<(Vec<VType>, VType)>),
Thread(VType), Thread(VType),
Reference(Box<Self>), Reference(VType),
EnumVariant(usize, VType), EnumVariant(usize, VType),
EnumVariantS(String, VType), EnumVariantS(String, VType),
CustomType(usize), CustomType(usize),
@ -50,33 +50,13 @@ impl VSingleType {
Self::String => Some(VSingleType::String.into()), Self::String => Some(VSingleType::String.into()),
Self::Tuple(t) => t.get(i).cloned(), Self::Tuple(t) => t.get(i).cloned(),
Self::List(t) => Some(t.clone()), Self::List(t) => Some(t.clone()),
Self::Reference(r) => r.get_ref(i, gsinfo), Self::Reference(r) => Some(r.get(i, gsinfo)?.reference()),
Self::CustomType(t) => gsinfo.custom_types[*t].get(i, gsinfo), Self::CustomType(t) => gsinfo.custom_types[*t].get(i, gsinfo),
&Self::CustomTypeS(_) => { &Self::CustomTypeS(_) => {
unreachable!("CustomTypeS instead of CustomType, compiler bug? [get]") unreachable!("CustomTypeS instead of CustomType, compiler bug? [get]")
} }
} }
} }
pub fn get_ref(&self, i: usize, gsinfo: &GlobalScriptInfo) -> Option<VType> {
match self {
Self::Any
| Self::Bool
| Self::Int
| Self::Float
| Self::Function(..)
| Self::Thread(..)
| Self::EnumVariant(..)
| Self::EnumVariantS(..) => None,
Self::String => Some(VSingleType::String.into()),
Self::Tuple(t) => t.get(i).map(|v| v.reference()),
Self::List(t) => Some(t.reference()),
Self::Reference(r) => r.get_ref(i, gsinfo),
Self::CustomType(t) => Some(gsinfo.custom_types[*t].get(i, gsinfo)?.reference()),
&Self::CustomTypeS(_) => {
unreachable!("CustomTypeS instead of CustomType, compiler bug? [get]")
}
}
}
/// None => might not always return t, Some(t) => can only return t /// None => might not always return t, Some(t) => can only return t
pub fn get_always(&self, i: usize, info: &GlobalScriptInfo) -> Option<VType> { pub fn get_always(&self, i: usize, info: &GlobalScriptInfo) -> Option<VType> {
match self { match self {
@ -166,19 +146,12 @@ impl VType {
pub fn dereference(&self, info: &GlobalScriptInfo) -> Option<Self> { pub fn dereference(&self, info: &GlobalScriptInfo) -> Option<Self> {
let mut out = Self::empty(); let mut out = Self::empty();
for t in self.types.iter() { for t in self.types.iter() {
out.add_type(t.deref()?, info); out.add_types(t.deref()?, info);
} }
Some(out) Some(out)
} }
pub fn reference(&self) -> Self { pub fn reference(&self) -> Self {
let _out = Self::empty(); VSingleType::Reference(self.clone()).to()
Self {
types: self
.types
.iter()
.map(|v| VSingleType::Reference(Box::new(v.clone())))
.collect(),
}
} }
} }
@ -232,9 +205,9 @@ impl VSingleType {
_ => false, _ => false,
} }
} }
pub fn deref(&self) -> Option<VSingleType> { pub fn deref(&self) -> Option<VType> {
if let Self::Reference(v) = self { if let Self::Reference(v) = self {
Some(*v.clone()) Some(v.clone())
} else { } else {
None None
} }
@ -361,7 +334,7 @@ impl VSingleType {
VType::empty() VType::empty()
} }
} }
Self::Reference(r) => r.inner_types_ref(info), Self::Reference(r) => r.inner_types(info).reference(),
_ => VType::empty(), _ => VType::empty(),
} }
} }
@ -375,7 +348,7 @@ impl VSingleType {
out out
} }
Self::List(v) => v.reference(), Self::List(v) => v.reference(),
Self::Reference(r) => r.inner_types_ref(info), Self::Reference(r) => r.inner_types(info).reference(),
_ => VType::empty(), _ => VType::empty(),
} }
} }
@ -424,7 +397,8 @@ impl VSingleType {
let o = match (self, rhs) { let o = match (self, rhs) {
(_, Self::Any) => true, (_, Self::Any) => true,
(Self::Any, _) => false, (Self::Any, _) => false,
(Self::Reference(r), Self::Reference(b)) => r.fits_in(b, info), // references have to be eq, not fits_in; otherwise whoever gets our reference could write invalid data to it!
(Self::Reference(a), Self::Reference(b)) => a.eq(b, info),
(Self::Reference(_), _) | (_, Self::Reference(_)) => false, (Self::Reference(_), _) | (_, Self::Reference(_)) => false,
(Self::EnumVariant(v1, t1), Self::EnumVariant(v2, t2)) => { (Self::EnumVariant(v1, t1), Self::EnumVariant(v2, t2)) => {
*v1 == *v2 && t1.fits_in(&t2, info).is_empty() *v1 == *v2 && t1.fits_in(&t2, info).is_empty()
@ -583,8 +557,16 @@ impl FormatGs for VSingleType {
write!(f, ")") write!(f, ")")
} }
Self::Reference(inner) => { Self::Reference(inner) => {
write!(f, "&")?; if inner.types.len() != 1 {
inner.fmtgs(f, info, form, file) write!(f, "&(")?;
} else {
write!(f, "&")?;
}
inner.fmtgs(f, info, form, file)?;
if inner.types.len() != 1 {
write!(f, ")")?;
}
Ok(())
} }
Self::EnumVariant(variant, inner) => { Self::EnumVariant(variant, inner) => {
if let Some(name) = if let Some(info) = info { if let Some(name) = if let Some(info) = info {

View File

@ -448,7 +448,7 @@ impl ByteData for VSingleType {
b'l' => Self::List(ByteData::from_byte_data(data)?), b'l' => Self::List(ByteData::from_byte_data(data)?),
b'F' => Self::Function(ByteData::from_byte_data(data)?), b'F' => Self::Function(ByteData::from_byte_data(data)?),
b'T' => Self::Thread(ByteData::from_byte_data(data)?), b'T' => Self::Thread(ByteData::from_byte_data(data)?),
b'R' => Self::Reference(Box::new(ByteData::from_byte_data(data)?)), b'R' => Self::Reference(ByteData::from_byte_data(data)?),
b'e' => Self::EnumVariant( b'e' => Self::EnumVariant(
ByteData::from_byte_data(data)?, ByteData::from_byte_data(data)?,
ByteData::from_byte_data(data)?, ByteData::from_byte_data(data)?,

View File

@ -312,6 +312,7 @@ pub enum ParseErrors {
FoundEofInFunctionArgName, FoundEofInFunctionArgName,
FoundEofInType, FoundEofInType,
FoundEofInsteadOfType, FoundEofInsteadOfType,
RefTypeWithBracketsNotClosedProperly,
InvalidType(String), InvalidType(String),
CannotUseFixedIndexingWithThisType(VType), CannotUseFixedIndexingWithThisType(VType),
CannotWrapWithThisStatement(SStatementEnum), CannotWrapWithThisStatement(SStatementEnum),
@ -350,6 +351,9 @@ impl FormatGs for ParseErrors {
} }
Self::FoundEofInType => write!(f, "found EOF in type."), Self::FoundEofInType => write!(f, "found EOF in type."),
Self::FoundEofInsteadOfType => write!(f, "expected type, found EOF instead."), Self::FoundEofInsteadOfType => write!(f, "expected type, found EOF instead."),
Self::RefTypeWithBracketsNotClosedProperly => {
write!(f, "ref type with brackets &(...) wasn't closed properly.")
}
Self::InvalidType(name) => write!(f, "\"{name}\" is not a type."), Self::InvalidType(name) => write!(f, "\"{name}\" is not a type."),
Self::CannotUseFixedIndexingWithThisType(t) => { Self::CannotUseFixedIndexingWithThisType(t) => {
write!(f, "cannot use fixed-indexing with type ")?; write!(f, "cannot use fixed-indexing with type ")?;
@ -1178,11 +1182,31 @@ pub mod implementation {
Ok(( Ok((
match file.next() { match file.next() {
Some('&') => { Some('&') => {
let parse_output = parse_single_type_adv(file, in_fn_args)?; let output = if let Some('(') = file.peek() {
if parse_output.1 { file.next();
closed_bracket_in_fn_args = true; let (parse_output, closed_bracket) = parse_type_adv(file, true)?;
} if !closed_bracket {
VSingleType::Reference(Box::new(parse_output.0)) return Err(ParseError {
err: ParseErrors::RefTypeWithBracketsNotClosedProperly,
location: err_start_of_single_type,
location_end: Some(*file.get_pos()),
context: vec![],
info: None,
});
}
if let Some(')') = file.peek() {
file.next();
closed_bracket_in_fn_args = true;
}
parse_output
} else {
let (o, i_f) = parse_single_type_adv(file, in_fn_args)?;
if i_f {
closed_bracket_in_fn_args = true;
}
o.to()
};
VSingleType::Reference(output)
} }
// Tuple or Array // Tuple or Array
Some('[') => { Some('[') => {