changed enum type syntax because A: int/string is ambiguous while A(int)/string and A(int/string) aren't. Builtins now use the Err enum variant for errors.

This commit is contained in:
Dummi26 2023-04-01 16:27:52 +02:00
parent b1a90d5872
commit 794e776e25
5 changed files with 147 additions and 95 deletions

View File

@ -1,12 +1 @@
x = if false enum_a: "hello" else "world"
x.debug()
switch! x {
string {
println("no enum")
x.println()
}
enum_a: string {
println("Enum!")
x.noenum().println()
}
}

View File

@ -522,14 +522,19 @@ fn parse_single_type_adv(
}
match file.next() {
Some(ch) if ch.is_whitespace() => break,
Some(':') => {
break 'parse_single_type VSingleType::EnumVariantS(name, {
let po = parse_type_adv(file, in_fn_args)?;
if po.1 {
closed_bracket_in_fn_args = true;
Some('(') => {
break 'parse_single_type if name.as_str() == "fn" {
todo!("fn types");
} else {
VSingleType::EnumVariantS(name, {
let po = parse_type_adv(file, true)?;
if !po.1 {
eprintln!("enum type should be closed by ')', but apparently wasn't?");
assert_eq!(file.next(), Some(')'));
}
po.0
})
};
}
Some(')') if in_fn_args => {

View File

@ -100,7 +100,7 @@ pub mod to_runnable {
use crate::{script::{
val_data::VDataEnum,
val_type::{VSingleType, VType},
val_type::{VSingleType, VType}, builtins,
}, libs};
use super::{
@ -168,7 +168,7 @@ pub mod to_runnable {
lib_fns.insert(name.to_string(), (libid, fnid));
}
}
Self { vars: 0, libs, lib_fns, enum_variants: HashMap::new() }
Self { vars: 0, libs, lib_fns, enum_variants: builtins::EVS.iter().enumerate().map(|(i, v)| (v.to_string(), i)).collect() }
}
}
// Local, used to keep local variables separated
@ -480,11 +480,30 @@ pub mod to_runnable {
types_not_covered_req_error = true;
types_not_covered = types_not_covered | {
let mut v = val_type;
fn make_readable(v: &mut VType, ginfo: &GInfo) {
for t in v.types.iter_mut() {
if let VSingleType::EnumVariant(i, v) = t {
*t = VSingleType::EnumVariantS(ginfo.enum_variants.iter().find_map(|(st, us)| if *us == *i { Some(st.clone()) } else { None }).unwrap(), v.clone());
match t {
VSingleType::EnumVariant(i, v) => {
let mut v = v.clone();
make_readable(&mut v, ginfo);
*t = VSingleType::EnumVariantS(ginfo.enum_variants.iter().find_map(|(st, us)| if *us == *i { Some(st.clone()) } else { None }).unwrap(), v);
},
VSingleType::EnumVariantS(_, v) => make_readable(v, ginfo),
VSingleType::Tuple(v) => for t in v.iter_mut() {
make_readable(t, ginfo)
}
VSingleType::List(t) => make_readable(t, ginfo),
VSingleType::Reference(v) => {
let mut v = v.clone().to();
make_readable(&mut v, ginfo);
assert_eq!(v.types.len(), 1);
*t = VSingleType::Reference(Box::new(v.types.remove(0)));
}
VSingleType::Bool | VSingleType::Int | VSingleType::Float | VSingleType::String | VSingleType::Function(..) | VSingleType::Thread(..) => (),
}
}
}
make_readable(&mut v, &ginfo);
v
};
}
@ -1025,8 +1044,8 @@ impl Display for VSingleType {
Self::Function(_) => write!(f, "FUNCTION"),
Self::Thread(_) => write!(f, "THREAD"),
Self::Reference(r) => write!(f, "&{r}"),
Self::EnumVariant(v, t) => write!(f, "{v}: {t}"),
Self::EnumVariantS(v, t) => write!(f, "{v}: {t}"),
Self::EnumVariant(v, t) => write!(f, "{v}({t})"),
Self::EnumVariantS(v, t) => write!(f, "{v}({t})"),
}
}
}
@ -1147,7 +1166,7 @@ impl Display for VDataEnum {
Self::Function(v) => write!(f, "{v}"),
Self::Thread(..) => write!(f, "THREAD"),
Self::Reference(r) => write!(f, "{}", r.lock().unwrap()),
Self::EnumVariant(v, d) => write!(f, "{v}: {d}"),
Self::EnumVariant(v, d) => write!(f, "{v}({d})"),
}
}
}

View File

@ -12,11 +12,16 @@ use super::{
val_type::{VSingleType, VType},
};
const EV_ERR: usize = 0;
// const EV_??? = 1;
pub const EVS: [&'static str; 1] = ["Err"];
#[derive(Clone, Debug)]
pub enum BuiltinFunction {
// core
Assume1, // assume []/[t] is [t], return t. Optionally provide a reason as to why (2nd arg)
NoEnum,
Matches,
// print
Print,
Println,
@ -26,7 +31,7 @@ pub enum BuiltinFunction {
// format
ToString,
Format,
// match
// parse
ParseInt,
ParseFloat,
// functions
@ -79,6 +84,7 @@ impl BuiltinFunction {
Some(match s {
"assume1" => Self::Assume1,
"noenum" => Self::NoEnum,
"matches" => Self::Matches,
"print" => Self::Print,
"println" => Self::Println,
"debug" => Self::Debug,
@ -141,14 +147,14 @@ impl BuiltinFunction {
1 => len1 = true,
_ => return false,
},
_ => return false,
_ => len1 = true,
}
}
if !len0 {
eprintln!("Warn: calling assume1 on a value of type {}, which will always be a length-1 tuple.", input[0]);
eprintln!("Warn: calling assume1 on a value of type {}, which will never be a length-0 tuple and therefore will not cannot fail.", input[0]);
}
if !len1 {
eprintln!("Warn: calling assume1 on a value of type {}, which will never be a length-1 tuple!", input[0]);
eprintln!("Warn: calling assume1 on a value of type {}, which will always be a length-0 tuple!", input[0]);
}
if input.len() >= 2 {
if input.len() == 2 {
@ -164,6 +170,7 @@ impl BuiltinFunction {
}
}
Self::NoEnum => input.len() == 1,
Self::Matches => input.len() == 1,
Self::Print | Self::Println => {
if input.len() == 1 {
input[0].fits_in(&VSingleType::String.to()).is_empty()
@ -332,12 +339,13 @@ impl BuiltinFunction {
out = out | &v[0];
}
}
_ => unreachable!(),
v => out = out | v.clone().to(),
}
}
out
}
Self::NoEnum => input[0].clone().noenum(),
Self::Matches => input[0].matches().1,
// []
Self::Print | Self::Println | Self::Debug | Self::Sleep => VType {
types: vec![VSingleType::Tuple(vec![])],
@ -410,37 +418,40 @@ impl BuiltinFunction {
Self::Exit => VType { types: vec![] }, // doesn't return
Self::FsList => VType {
types: vec![
VSingleType::Tuple(vec![]).into(),
VSingleType::List(VSingleType::String.into()).into(),
VSingleType::List(VSingleType::String.into()),
VSingleType::EnumVariant(EV_ERR, VSingleType::String.to()),
],
},
Self::FsRead => VType {
types: vec![
VSingleType::Tuple(vec![]).into(),
VSingleType::List(VSingleType::Int.into()).into(),
VSingleType::List(VSingleType::Int.to()),
VSingleType::EnumVariant(EV_ERR, VSingleType::String.to()),
],
},
Self::FsWrite => VType {
types: vec![
VSingleType::Tuple(vec![]).into(),
VSingleType::List(VSingleType::String.into()).into(),
VSingleType::EnumVariant(EV_ERR, VSingleType::String.to()),
],
},
Self::BytesToString => VType {
types: vec![
VSingleType::String.into(),
VSingleType::String,
VSingleType::EnumVariant(
EV_ERR,
VSingleType::Tuple(vec![
VSingleType::String.into(), // lossy string
VSingleType::String.into(), // error message
])
.into(),
.to(),
),
],
},
Self::StringToBytes => VSingleType::List(VSingleType::Int.into()).into(),
Self::RunCommand => VType {
types: vec![
// error
VSingleType::String.into(),
VSingleType::EnumVariant(EV_ERR, VSingleType::String.to()),
// success: Option<ExitCode>, stdout, stderr
VSingleType::Tuple(vec![
VType {
@ -454,7 +465,7 @@ impl BuiltinFunction {
Self::RunCommandGetBytes => VType {
types: vec![
// error
VSingleType::String.into(),
VSingleType::EnumVariant(EV_ERR, VSingleType::String.to()),
// success: Option<ExitCode>, stdout, stderr
VSingleType::Tuple(vec![
VType {
@ -502,18 +513,10 @@ impl BuiltinFunction {
Self::Substring => VSingleType::String.into(),
Self::Regex => VType {
types: vec![
VSingleType::Tuple(vec![
// does match
VSingleType::Tuple(vec![VSingleType::List(VSingleType::String.to()).to()])
.to(),
// no error
]),
VSingleType::Tuple(vec![
// does not match
VSingleType::Tuple(vec![]).to(),
// error
VSingleType::String.to(),
]),
// [string ...]
VSingleType::List(VSingleType::String.to()),
// Err(string)
VSingleType::EnumVariant(EV_ERR, VSingleType::String.to()),
],
},
}
@ -525,9 +528,10 @@ impl BuiltinFunction {
libs: &Arc<Vec<libs::Lib>>,
) -> VData {
match self {
Self::Assume1 => {
if let VDataEnum::Tuple(mut v) = args[0].run(vars, libs).data {
v.pop().unwrap()
Self::Assume1 => match args[0].run(vars, libs).data {
VDataEnum::Tuple(mut v) => {
if let Some(v) = v.pop() {
v
} else {
panic!(
"ASSUMPTION FAILED: assume1 :: {}",
@ -543,7 +547,13 @@ impl BuiltinFunction {
);
}
}
v => v.to(),
},
Self::NoEnum => args[0].run(vars, libs).noenum(),
Self::Matches => match args[0].run(vars, libs).data.matches() {
Some(v) => VDataEnum::Tuple(vec![v]).to(),
None => VDataEnum::Tuple(vec![]).to(),
},
BuiltinFunction::Print => {
if let VDataEnum::String(arg) = args[0].run(vars, libs).data {
print!("{}", arg);
@ -704,8 +714,8 @@ impl BuiltinFunction {
if args.len() > 1 {
todo!("fs_list advanced filters")
}
if let Ok(entries) = std::fs::read_dir(path) {
VDataEnum::List(
match std::fs::read_dir(path) {
Ok(entries) => VDataEnum::List(
VSingleType::String.into(),
entries
.filter_map(|entry| {
@ -722,9 +732,12 @@ impl BuiltinFunction {
})
.collect(),
)
.to()
} else {
VDataEnum::Tuple(vec![]).to()
.to(),
Err(e) => VDataEnum::EnumVariant(
EV_ERR,
Box::new(VDataEnum::String(e.to_string()).to()),
)
.to(),
}
} else {
unreachable!("fs_list first arg not a string")
@ -736,16 +749,19 @@ impl BuiltinFunction {
Self::FsRead => {
if args.len() > 0 {
if let VDataEnum::String(path) = args[0].run(vars, libs).data {
if let Ok(data) = std::fs::read(path) {
VDataEnum::List(
match std::fs::read(path) {
Ok(data) => VDataEnum::List(
VSingleType::Int.into(),
data.into_iter()
.map(|v| VDataEnum::Int(v as _).to())
.collect(),
)
.to()
} else {
VDataEnum::Tuple(vec![]).to()
.to(),
Err(e) => VDataEnum::EnumVariant(
EV_ERR,
Box::new(VDataEnum::String(e.to_string()).to()),
)
.to(),
}
} else {
unreachable!("fs_read first arg not a string")
@ -766,7 +782,11 @@ impl BuiltinFunction {
}
match std::fs::write(file_path, bytes) {
Ok(_) => VDataEnum::Tuple(vec![]).to(),
Err(e) => VDataEnum::String(e.to_string()).to(),
Err(e) => VDataEnum::EnumVariant(
EV_ERR,
Box::new(VDataEnum::String(e.to_string()).to()),
)
.to(),
}
} else {
unreachable!(
@ -788,13 +808,20 @@ impl BuiltinFunction {
Ok(v) => VDataEnum::String(v).to(),
Err(e) => {
let err = e.to_string();
VDataEnum::EnumVariant(
EV_ERR,
Box::new(
VDataEnum::Tuple(vec![
VDataEnum::String(
String::from_utf8_lossy(&e.into_bytes()).into_owned(),
String::from_utf8_lossy(&e.into_bytes())
.into_owned(),
)
.to(),
VDataEnum::String(err).to(),
])
.to(),
),
)
.to()
}
}
@ -876,7 +903,11 @@ impl BuiltinFunction {
.to(),
])
.to(),
Err(e) => VDataEnum::String(e.to_string()).to(),
Err(e) => VDataEnum::EnumVariant(
EV_ERR,
Box::new(VDataEnum::String(e.to_string()).to()),
)
.to(),
}
} else {
unreachable!("run_command not string arg")
@ -1345,11 +1376,17 @@ impl BuiltinFunction {
.to()])
.to()
}
Err(e) => VDataEnum::Tuple(vec![
Err(e) => VDataEnum::EnumVariant(
EV_ERR,
Box::new(
VDataEnum::Tuple(vec![
VDataEnum::Tuple(vec![]).to(), // no results
VDataEnum::String(e.to_string()).to(),
])
.to(),
),
)
.to(),
}
} else {
unreachable!()

View File

@ -106,6 +106,7 @@ impl VDataEnum {
None
}
}
VDataEnum::EnumVariant(..) => None,
other => Some(other.to()),
}
}
@ -119,6 +120,7 @@ impl VSingleType {
None => (true, VType { types: vec![] }),
},
Self::Bool => (true, Self::Bool.to()),
Self::EnumVariant(..) | Self::EnumVariantS(..) => (true, VType { types: vec![] }),
v => (false, v.clone().to()),
}
}