changed VType internals

This commit is contained in:
mark 2023-06-06 13:51:33 +02:00
parent f7feb688e8
commit 1c749da401
8 changed files with 161 additions and 155 deletions

View File

@ -381,7 +381,7 @@ impl BuiltinFunction {
if let Some(true) = vec.is_reference() {
if let Some(t) = vec.get_any(info) {
el.fits_in(
&t.dereference()
&t.dereference(info)
.expect("running get() on &[ ...] should give a reference"),
info,
)
@ -402,7 +402,7 @@ impl BuiltinFunction {
if let Some(true) = vec.is_reference() {
if let Some(t) = vec.get_any(info) {
el.fits_in(
&t.dereference()
&t.dereference(info)
.expect("running get() on a &[ ...] should give a reference."),
info,
)
@ -519,10 +519,10 @@ impl BuiltinFunction {
match t {
VSingleType::Tuple(v) => {
if !v.is_empty() {
out = out | &v[0];
out.add_typesr(&v[0], info)
}
}
v => out = out | v.clone().to(),
v => out.add_typer(v, info),
}
}
out
@ -532,15 +532,15 @@ impl BuiltinFunction {
for t in &input[0].types {
match t {
VSingleType::EnumVariant(..) | VSingleType::EnumVariantS(..) => (),
t => out = out | t.clone().to(),
t => out.add_typer(t, info),
}
}
out
}
Self::NoEnum => input[0].clone().noenum(),
Self::Matches => input[0].matches().1,
Self::NoEnum => input[0].clone().noenum(info),
Self::Matches => input[0].matches(info).1,
Self::Clone => input[0]
.dereference()
.dereference(info)
.expect("type is a reference, so it can be dereferenced"),
// []
Self::Print | Self::Println | Self::Debug | Self::Sleep => VType {
@ -562,7 +562,8 @@ impl BuiltinFunction {
for func in &funcs.types {
if let VSingleType::Function(io) = func {
let mut empty = true;
let fn_out = io.iter().fold(VType::empty(), |t, (fn_in, fn_out)| {
let fn_out =
io.iter().fold(VType::empty(), |mut t, (fn_in, fn_out)| {
if fn_in.len() == (input.len() - 1)
&& fn_in
.iter()
@ -570,17 +571,16 @@ impl BuiltinFunction {
.all(|(fn_in, arg)| arg.fits_in(fn_in, info).is_empty())
{
empty = false;
t | fn_out.clone()
} else {
t
t.add_typesr(fn_out, info);
}
t
});
if empty {
unreachable!(
"fn args are incorrect for builtin run() or thread()!"
);
}
out = out | fn_out;
out.add_types(fn_out, info);
} else {
unreachable!("run called, first arg not a function")
}
@ -599,7 +599,7 @@ impl BuiltinFunction {
let mut out = VType { types: vec![] };
for v in &v.types {
if let VSingleType::Thread(v) = v {
out = out | v;
out.add_typesr(v, info);
} else {
unreachable!("await called with non-thread arg")
}
@ -611,7 +611,7 @@ impl BuiltinFunction {
}
Self::Pop => {
if let Some(v) = input.first() {
if let Some(v) = v.dereference() {
if let Some(v) = v.dereference(info) {
VType {
types: vec![
VSingleType::Tuple(vec![]),
@ -629,14 +629,14 @@ impl BuiltinFunction {
}
Self::Remove => {
if input[1].fits_in(&VSingleType::Int.to(), info).is_empty() {
if let Some(v) = input[0].dereference() {
if let Some(v) = input[0].dereference(info) {
VType {
types: vec![
VSingleType::Tuple(vec![]),
VSingleType::Tuple(vec![v
.get_any(info)
.expect("cannot use get on this type")
.dereference()
.dereference(info)
.expect(
"running get_any() on &[ ...] should give a reference...",
)]),
@ -745,7 +745,7 @@ impl BuiltinFunction {
(false, false) => (),
}
}
let o = match (
let mut o = match (
(
input[0].contains(&VSingleType::Int, info),
input[0].contains(&VSingleType::Float, info),
@ -763,10 +763,9 @@ impl BuiltinFunction {
_ => VSingleType::Float.to(),
};
if might_be_string {
o | VSingleType::String.to()
} else {
o
o.add_type(VSingleType::String, info);
}
o
} else {
unreachable!("called add/sub/mul/div/mod/pow with args != 2")
}

View File

@ -83,7 +83,7 @@ impl RFunction {
let out = self
.out_map
.iter()
.fold(VType::empty(), |t, (fn_in, fn_out)| {
.fold(VType::empty(), |mut t, (fn_in, fn_out)| {
if fn_in.len() == (input_types.len())
&& fn_in
.iter()
@ -91,10 +91,9 @@ impl RFunction {
.all(|(fn_in, arg)| arg.fits_in(fn_in, info).is_empty())
{
empty = false;
t | fn_out.clone()
} else {
t
t.add_typesr(fn_out, info);
}
t
});
if empty {
None
@ -102,9 +101,12 @@ impl RFunction {
Some(out)
}
}
pub fn out_all(&self, _info: &GlobalScriptInfo) -> VType {
pub fn out_all(&self, info: &GlobalScriptInfo) -> VType {
// self.statement.out(info)
self.out_map.iter().fold(VType::empty(), |t, (_, v)| t | v)
self.out_map.iter().fold(VType::empty(), |mut t, (_, v)| {
t.add_typesr(v, info);
t
})
}
pub fn in_types(&self) -> &Vec<VType> {
&self.input_types
@ -155,7 +157,7 @@ impl RStatement {
}
let mut o = self.statement.out(info);
for _ in 0..self.derefs {
o = o.dereference().expect("can't dereference (out())");
o = o.dereference(info).expect("can't dereference (out())");
}
o
}
@ -177,7 +179,7 @@ impl RStatementEnum {
let mut out = VType { types: vec![] };
for v in v {
let val = v.run(info);
out = out | val.out();
out.add_types(val.out(), &info);
w.push(val);
}
VDataEnum::List(out, w).to()
@ -331,7 +333,7 @@ impl RStatementEnum {
Self::List(v) => VSingleType::List({
let mut types = VType { types: vec![] };
for t in v {
types = types | t.out(info);
types.add_types(t.out(info), info);
}
types
})
@ -358,14 +360,20 @@ impl RStatementEnum {
Self::LibFunctionCall(.., out) => out.clone(),
Self::Block(b) => b.out(info),
Self::If(_, a, b) => {
let mut out = a.out(info);
if let Some(b) = b {
a.out(info) | b.out(info)
out.add_types(b.out(info), info);
} else {
a.out(info) | VSingleType::Tuple(vec![]).to()
out.add_type(VSingleType::Tuple(vec![]), info);
}
out
}
Self::Loop(c) => c.out(info).matches(info).1,
Self::For(_, _, b) => {
let mut out = b.out(info).matches(info).1;
out.add_type(VSingleType::Tuple(vec![]), info);
out
}
Self::Loop(c) => c.out(info).matches().1,
Self::For(_, _, b) => VSingleType::Tuple(vec![]).to() | b.out(info).matches().1,
Self::BuiltinFunctionCall(f, args) => {
f.returns(args.iter().map(|rs| rs.out(info)).collect(), info)
}
@ -379,7 +387,7 @@ impl RStatementEnum {
};
for switch_on in switch_on {
for (_on_type, _assign_to, case) in cases.iter() {
out = out | case.out(info);
out.add_types(case.out(info), info);
}
}
out
@ -388,14 +396,14 @@ impl RStatementEnum {
let mut out = VType::empty();
let mut can_fail_to_match = true;
for (condition, _assign_to, action) in cases {
out = out | action.out(info);
if !condition.out(info).matches().0 {
out.add_types(action.out(info), info);
if !condition.out(info).matches(info).0 {
can_fail_to_match = false;
break;
}
}
if can_fail_to_match {
out = out | VSingleType::Tuple(vec![]).to()
out.add_type(VSingleType::Tuple(vec![]), info);
}
out
}

View File

@ -508,18 +508,20 @@ fn statement_adv(
let lib = &ginfo.libs[*libid];
let libfn = &lib.registered_fns[*fnid];
let mut empty = true;
let fn_out = libfn.1.iter().fold(VType::empty(), |t, (fn_in, fn_out)| {
if fn_in.len() == arg_types.len()
&& fn_in
let fn_out =
libfn
.1
.iter()
.zip(arg_types.iter())
.all(|(fn_in, arg)| arg.fits_in(fn_in, ginfo).is_empty())
.fold(VType::empty(), |mut t, (fn_in, fn_out)| {
if fn_in.len() == arg_types.len()
&& fn_in.iter().zip(arg_types.iter()).all(|(fn_in, arg)| {
arg.fits_in(fn_in, ginfo).is_empty()
})
{
empty = false;
t | fn_out.clone()
} else {
t
t.add_typesr(fn_out, ginfo);
}
t
});
if empty {
return Err(ToRunnableError::WrongArgsForLibFunction(
@ -579,7 +581,7 @@ fn statement_adv(
SStatementEnum::For(v, c, b) => {
let mut linfo = linfo.clone();
let container = statement(&c, ginfo, &mut linfo)?;
let inner = container.out(ginfo).inner_types();
let inner = container.out(ginfo).inner_types(ginfo);
if inner.types.is_empty() {
return Err(ToRunnableError::ForLoopContainerHasNoInnerTypes);
}
@ -601,7 +603,7 @@ fn statement_adv(
stypes(&mut v, ginfo)?;
v
};
covered_types = covered_types | &case_type;
covered_types.add_typesr(&case_type, ginfo);
ncases.push((
case_type.clone(),
statement_adv(
@ -633,7 +635,7 @@ fn statement_adv(
for (condition, assign_to, action) in cases.iter() {
let mut linfo = linfo.clone();
let condition = statement(condition, ginfo, &mut linfo)?;
let (can_fail, matches) = condition.out(ginfo).matches();
let (can_fail, matches) = condition.out(ginfo).matches(ginfo);
let assign_to = statement_adv(
assign_to,
ginfo,
@ -647,7 +649,7 @@ fn statement_adv(
}
}
if may_not_match {
out_type = out_type | VSingleType::Tuple(vec![]).to();
out_type.add_type(VSingleType::Tuple(vec![]), ginfo);
}
RStatementEnum::Match(ncases).to()

View File

@ -417,13 +417,13 @@ impl VSingleType {
}
impl VType {
/// returns (can_fail_to_match, matches_as)
pub fn matches(&self) -> (bool, VType) {
pub fn matches(&self, info: &GlobalScriptInfo) -> (bool, VType) {
let mut can_fail = false;
let mut matches_as = VType { types: vec![] };
for t in self.types.iter() {
let (f, t) = t.matches();
can_fail |= f;
matches_as = matches_as | t;
matches_as.add_types(t, info);
}
(can_fail, matches_as)
}

View File

@ -14,12 +14,12 @@ use super::{
use super::global_info::LogMsg;
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug)]
pub struct VType {
pub types: Vec<VSingleType>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug)]
pub enum VSingleType {
Any,
Bool,
@ -128,21 +128,21 @@ impl VType {
pub fn get(&self, i: usize, info: &GlobalScriptInfo) -> Option<VType> {
let mut out = VType { types: vec![] };
for t in &self.types {
out = out | t.get(i, info)?; // if we can't use *get* on one type, we can't use it at all.
out.add_types(t.get(i, info)?, info); // if we can't use *get* on one type, we can't use it at all.
}
Some(out)
}
pub fn get_always(&self, i: usize, info: &GlobalScriptInfo) -> Option<VType> {
let mut out = VType { types: vec![] };
for t in &self.types {
out = out | t.get_always(i, info)?; // if we can't use *get* on one type, we can't use it at all.
out.add_types(t.get_always(i, info)?, info); // if we can't use *get* on one type, we can't use it at all.
}
Some(out)
}
pub fn get_always_ref(&self, i: usize, info: &GlobalScriptInfo) -> Option<VType> {
let mut out = VType { types: vec![] };
for t in &self.types {
out = out | t.get_always_ref(i, info)?; // if we can't use *get* on one type, we can't use it at all.
out.add_types(t.get_always_ref(i, info)?, info); // if we can't use *get* on one type, we can't use it at all.
}
Some(out)
}
@ -165,10 +165,10 @@ impl VType {
}
}
/// returns Some(t) where t is the type you get from dereferencing self or None if self contains even a single type that cannot be dereferenced.
pub fn dereference(&self) -> Option<Self> {
pub fn dereference(&self, info: &GlobalScriptInfo) -> Option<Self> {
let mut out = Self::empty();
for t in self.types.iter() {
out = out | t.deref()?.to();
out.add_type(t.deref()?, info);
}
Some(out)
}
@ -194,7 +194,10 @@ impl VSingleType {
| Self::Function(..)
| Self::Thread(..) => None,
Self::String => Some(VSingleType::String.into()),
Self::Tuple(t) => Some(t.iter().fold(VType { types: vec![] }, |a, b| a | b)),
Self::Tuple(t) => Some(t.iter().fold(VType::empty(), |mut a, b| {
a.add_typesr(b, info);
a
})),
Self::List(t) => Some(t.clone()),
Self::Reference(r) => r.get_any_ref(info),
Self::EnumVariant(_, t) => t.get_any(info),
@ -212,10 +215,10 @@ impl VSingleType {
| Self::Function(..)
| Self::Thread(..) => None,
Self::String => Some(VSingleType::String.into()),
Self::Tuple(t) => Some(
t.iter()
.fold(VType { types: vec![] }, |a, b| a | b.reference()),
),
Self::Tuple(t) => Some(t.iter().fold(VType::empty(), |mut a, b| {
a.add_types(b.reference(), info);
a
})),
Self::List(t) => Some(t.reference()),
// TODO: idk if this is right...
Self::Reference(r) => r.get_any_ref(info),
@ -243,14 +246,14 @@ impl VType {
pub fn get_any(&self, info: &GlobalScriptInfo) -> Option<VType> {
let mut out = VType { types: vec![] };
for t in &self.types {
out = out | t.get_any(info)?; // if we can't use *get* on one type, we can't use it at all.
out.add_types(t.get_any(info)?, info); // if we can't use *get* on one type, we can't use it at all.
}
Some(out)
}
pub fn get_any_ref(&self, info: &GlobalScriptInfo) -> Option<VType> {
let mut out = VType { types: vec![] };
for t in &self.types {
out = out | t.get_any_ref(info)?; // if we can't use *get* on one type, we can't use it at all.
out.add_types(t.get_any_ref(info)?, info); // if we can't use *get* on one type, we can't use it at all.
}
Some(out)
}
@ -272,12 +275,10 @@ impl VType {
}
no
}
pub fn inner_types(&self) -> VType {
pub fn inner_types(&self, info: &GlobalScriptInfo) -> VType {
let mut out = VType { types: vec![] };
for t in &self.types {
for it in t.inner_types() {
out = out | it.to();
}
out.add_types(t.inner_types(info), info);
}
out
}
@ -289,36 +290,45 @@ impl VType {
pub fn contains(&self, t: &VSingleType, info: &GlobalScriptInfo) -> bool {
t.fits_in_type(self, info)
}
pub fn noenum(self) -> Self {
pub fn noenum(self, info: &GlobalScriptInfo) -> Self {
let mut o = Self { types: vec![] };
for t in self.types {
o = o | t.noenum();
o.add_types(t.noenum(), info);
}
o
}
}
impl BitOr for VType {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
let mut types = self.types;
for t in rhs.types {
if !types.contains(&t) {
types.push(t)
}
}
Self { types }
impl VType {
pub fn eq(&self, rhs: &Self, info: &GlobalScriptInfo) -> bool {
self.fits_in(rhs, info).is_empty() && rhs.fits_in(self, info).is_empty()
}
}
impl BitOr<&VType> for VType {
type Output = Self;
fn bitor(self, rhs: &Self) -> Self::Output {
let mut types = self.types;
for t in &rhs.types {
if !types.contains(t) {
types.push(t.clone())
impl VSingleType {
pub fn eq(&self, rhs: &Self, info: &GlobalScriptInfo) -> bool {
self.fits_in(rhs, info) && rhs.fits_in(self, info)
}
}
impl VType {
pub fn add_types(&mut self, new: Self, info: &GlobalScriptInfo) {
for t in new.types {
self.add_type(t, info)
}
}
Self { types }
pub fn add_type(&mut self, new: VSingleType, info: &GlobalScriptInfo) {
if !self.contains(&new, info) {
self.types.push(new)
}
}
pub fn add_typesr(&mut self, new: &Self, info: &GlobalScriptInfo) {
for t in &new.types {
self.add_typer(t, info)
}
}
pub fn add_typer(&mut self, new: &VSingleType, info: &GlobalScriptInfo) {
if !self.contains(new, info) {
self.types.push(new.clone())
}
}
}
@ -326,65 +336,49 @@ impl VSingleType {
pub fn to(self) -> VType {
VType { types: vec![self] }
}
pub fn inner_types(&self) -> Vec<VSingleType> {
pub fn inner_types(&self, info: &GlobalScriptInfo) -> VType {
match self {
Self::Tuple(v) => {
let mut types = vec![];
let mut out = VType::empty();
for it in v {
// the tuple values
for it in &it.types {
// the possible types for each value
if !types.contains(it) {
types.push(it.clone());
out.add_typesr(it, info);
}
out
}
}
types
}
Self::List(v) => v.types.clone(),
Self::List(v) => v.clone(),
// NOTE: to make ints work in for loops
Self::Int => vec![Self::Int],
Self::Int => Self::Int.to(),
// for iterators in for loops: the match of the function's returned value make up the inner type
Self::Function(f) => {
// function that takes no inputs
if let Some(out) = f.iter().find_map(|(args, out)| {
if args.is_empty() {
Some(out.clone().inner_types())
Some(out.clone())
} else {
None
}
}) {
out.types
out
} else {
vec![]
VType::empty()
}
}
Self::Reference(r) => r.inner_types_ref(),
_ => vec![],
Self::Reference(r) => r.inner_types_ref(info),
_ => VType::empty(),
}
}
pub fn inner_types_ref(&self) -> Vec<VSingleType> {
pub fn inner_types_ref(&self, info: &GlobalScriptInfo) -> VType {
match self {
Self::Tuple(v) => {
let mut types = vec![];
let mut out = VType::empty();
for it in v {
// the tuple values
for it in &it.types {
// the possible types for each value
if !types.contains(it) {
types.push(Self::Reference(Box::new(it.clone())));
out.add_types(it.reference(), info);
}
out
}
}
types
}
Self::List(v) => v
.types
.iter()
.map(|v| Self::Reference(Box::new(v.clone())))
.collect(),
Self::Reference(r) => r.inner_types_ref(),
_ => vec![],
Self::List(v) => v.reference(),
Self::Reference(r) => r.inner_types_ref(info),
_ => VType::empty(),
}
}
pub fn noenum(self) -> VType {

View File

@ -5,7 +5,7 @@ mod lang;
mod libs;
mod parsing;
pub use lang::{val_data::*, val_type::*};
pub use lang::{global_info::GlobalScriptInfo, val_data::*, val_type::*};
pub use libs::{
comms::{ByteData, ByteDataA, Message, RespondableMessage},
inlib::MyLib,
@ -14,7 +14,10 @@ pub use parsing::*;
pub mod prelude {
pub use super::{
lang::{val_data::*, val_type::*},
lang::{
val_data::{VData, VDataEnum},
val_type::{VSingleType, VType},
},
MyLib, RespondableMessage,
};
}

View File

@ -495,8 +495,9 @@ impl ByteDataA for VDataEnum {
vec.push(b't');
c.as_byte_data(vec);
}
Self::List(_, data) => {
Self::List(t, data) => {
vec.push(b'l');
t.as_byte_data(vec);
data.as_byte_data(vec);
}
// TODO?
@ -525,13 +526,10 @@ impl ByteData for VDataEnum {
b'f' => Self::Float(ByteData::from_byte_data(data)?),
b'"' => Self::String(ByteData::from_byte_data(data)?),
b't' => Self::Tuple(ByteData::from_byte_data(data)?),
b'l' => {
let entries: Vec<VData> = ByteData::from_byte_data(data)?;
Self::List(
entries.iter().fold(VType::empty(), |t, v| t | v.out()),
entries,
)
}
b'l' => Self::List(
ByteData::from_byte_data(data)?,
ByteData::from_byte_data(data)?,
),
b'E' => Self::EnumVariant(
ByteData::from_byte_data(data)?,
Box::new(ByteData::from_byte_data(data)?),

View File

@ -1,6 +1,6 @@
use std::io::Cursor;
use mers_libs::prelude::*;
use mers_libs::{prelude::*, GlobalScriptInfo};
use mers_libs::{ByteData, ByteDataA};
#[test]
@ -14,9 +14,10 @@ fn list_type() {
);
let a = VSingleType::List(VSingleType::Int.to()).to();
assert_eq!(
VType::from_byte_data(&mut Cursor::new(a.as_byte_data_vec())).unwrap(),
a
assert!(
VType::from_byte_data(&mut Cursor::new(a.as_byte_data_vec()))
.unwrap()
.eq(&a, &GlobalScriptInfo::default()),
);
let a = VSingleType::Tuple(vec![
@ -27,8 +28,9 @@ fn list_type() {
VSingleType::EnumVariant(12, VSingleType::Float.to()).to(),
])
.to();
assert_eq!(
VType::from_byte_data(&mut Cursor::new(a.as_byte_data_vec())).unwrap(),
a
assert!(
VType::from_byte_data(&mut Cursor::new(a.as_byte_data_vec()))
.unwrap()
.eq(&a, &GlobalScriptInfo::default())
);
}