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() { match file.next() {
Some(ch) if ch.is_whitespace() => break, Some(ch) if ch.is_whitespace() => break,
Some(':') => { Some('(') => {
break 'parse_single_type VSingleType::EnumVariantS(name, { break 'parse_single_type if name.as_str() == "fn" {
let po = parse_type_adv(file, in_fn_args)?; todo!("fn types");
if po.1 { } else {
closed_bracket_in_fn_args = true; 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 po.0
}) })
};
} }
Some(')') if in_fn_args => { Some(')') if in_fn_args => {

View File

@ -100,7 +100,7 @@ pub mod to_runnable {
use crate::{script::{ use crate::{script::{
val_data::VDataEnum, val_data::VDataEnum,
val_type::{VSingleType, VType}, val_type::{VSingleType, VType}, builtins,
}, libs}; }, libs};
use super::{ use super::{
@ -168,7 +168,7 @@ pub mod to_runnable {
lib_fns.insert(name.to_string(), (libid, fnid)); 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 // Local, used to keep local variables separated
@ -480,11 +480,30 @@ pub mod to_runnable {
types_not_covered_req_error = true; types_not_covered_req_error = true;
types_not_covered = types_not_covered | { types_not_covered = types_not_covered | {
let mut v = val_type; let mut v = val_type;
fn make_readable(v: &mut VType, ginfo: &GInfo) {
for t in v.types.iter_mut() { for t in v.types.iter_mut() {
if let VSingleType::EnumVariant(i, v) = t { match t {
*t = VSingleType::EnumVariantS(ginfo.enum_variants.iter().find_map(|(st, us)| if *us == *i { Some(st.clone()) } else { None }).unwrap(), v.clone()); 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 v
}; };
} }
@ -1025,8 +1044,8 @@ impl Display for VSingleType {
Self::Function(_) => write!(f, "FUNCTION"), Self::Function(_) => write!(f, "FUNCTION"),
Self::Thread(_) => write!(f, "THREAD"), Self::Thread(_) => write!(f, "THREAD"),
Self::Reference(r) => write!(f, "&{r}"), Self::Reference(r) => write!(f, "&{r}"),
Self::EnumVariant(v, t) => write!(f, "{v}: {t}"), Self::EnumVariant(v, t) => write!(f, "{v}({t})"),
Self::EnumVariantS(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::Function(v) => write!(f, "{v}"),
Self::Thread(..) => write!(f, "THREAD"), Self::Thread(..) => write!(f, "THREAD"),
Self::Reference(r) => write!(f, "{}", r.lock().unwrap()), 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}, val_type::{VSingleType, VType},
}; };
const EV_ERR: usize = 0;
// const EV_??? = 1;
pub const EVS: [&'static str; 1] = ["Err"];
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum BuiltinFunction { pub enum BuiltinFunction {
// core // core
Assume1, // assume []/[t] is [t], return t. Optionally provide a reason as to why (2nd arg) Assume1, // assume []/[t] is [t], return t. Optionally provide a reason as to why (2nd arg)
NoEnum, NoEnum,
Matches,
// print // print
Print, Print,
Println, Println,
@ -26,7 +31,7 @@ pub enum BuiltinFunction {
// format // format
ToString, ToString,
Format, Format,
// match // parse
ParseInt, ParseInt,
ParseFloat, ParseFloat,
// functions // functions
@ -79,6 +84,7 @@ impl BuiltinFunction {
Some(match s { Some(match s {
"assume1" => Self::Assume1, "assume1" => Self::Assume1,
"noenum" => Self::NoEnum, "noenum" => Self::NoEnum,
"matches" => Self::Matches,
"print" => Self::Print, "print" => Self::Print,
"println" => Self::Println, "println" => Self::Println,
"debug" => Self::Debug, "debug" => Self::Debug,
@ -141,14 +147,14 @@ impl BuiltinFunction {
1 => len1 = true, 1 => len1 = true,
_ => return false, _ => return false,
}, },
_ => return false, _ => len1 = true,
} }
} }
if !len0 { 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 { 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 {
if input.len() == 2 { if input.len() == 2 {
@ -164,6 +170,7 @@ impl BuiltinFunction {
} }
} }
Self::NoEnum => input.len() == 1, Self::NoEnum => input.len() == 1,
Self::Matches => input.len() == 1,
Self::Print | Self::Println => { Self::Print | Self::Println => {
if input.len() == 1 { if input.len() == 1 {
input[0].fits_in(&VSingleType::String.to()).is_empty() input[0].fits_in(&VSingleType::String.to()).is_empty()
@ -332,12 +339,13 @@ impl BuiltinFunction {
out = out | &v[0]; out = out | &v[0];
} }
} }
_ => unreachable!(), v => out = out | v.clone().to(),
} }
} }
out out
} }
Self::NoEnum => input[0].clone().noenum(), Self::NoEnum => input[0].clone().noenum(),
Self::Matches => input[0].matches().1,
// [] // []
Self::Print | Self::Println | Self::Debug | Self::Sleep => VType { Self::Print | Self::Println | Self::Debug | Self::Sleep => VType {
types: vec![VSingleType::Tuple(vec![])], types: vec![VSingleType::Tuple(vec![])],
@ -410,37 +418,40 @@ impl BuiltinFunction {
Self::Exit => VType { types: vec![] }, // doesn't return Self::Exit => VType { types: vec![] }, // doesn't return
Self::FsList => VType { Self::FsList => VType {
types: vec![ types: vec![
VSingleType::Tuple(vec![]).into(), VSingleType::List(VSingleType::String.into()),
VSingleType::List(VSingleType::String.into()).into(), VSingleType::EnumVariant(EV_ERR, VSingleType::String.to()),
], ],
}, },
Self::FsRead => VType { Self::FsRead => VType {
types: vec![ types: vec![
VSingleType::Tuple(vec![]).into(), VSingleType::List(VSingleType::Int.to()),
VSingleType::List(VSingleType::Int.into()).into(), VSingleType::EnumVariant(EV_ERR, VSingleType::String.to()),
], ],
}, },
Self::FsWrite => VType { Self::FsWrite => VType {
types: vec![ types: vec![
VSingleType::Tuple(vec![]).into(), VSingleType::Tuple(vec![]).into(),
VSingleType::List(VSingleType::String.into()).into(), VSingleType::EnumVariant(EV_ERR, VSingleType::String.to()),
], ],
}, },
Self::BytesToString => VType { Self::BytesToString => VType {
types: vec![ types: vec![
VSingleType::String.into(), VSingleType::String,
VSingleType::EnumVariant(
EV_ERR,
VSingleType::Tuple(vec![ VSingleType::Tuple(vec![
VSingleType::String.into(), // lossy string VSingleType::String.into(), // lossy string
VSingleType::String.into(), // error message VSingleType::String.into(), // error message
]) ])
.into(), .to(),
),
], ],
}, },
Self::StringToBytes => VSingleType::List(VSingleType::Int.into()).into(), Self::StringToBytes => VSingleType::List(VSingleType::Int.into()).into(),
Self::RunCommand => VType { Self::RunCommand => VType {
types: vec![ types: vec![
// error // error
VSingleType::String.into(), VSingleType::EnumVariant(EV_ERR, VSingleType::String.to()),
// success: Option<ExitCode>, stdout, stderr // success: Option<ExitCode>, stdout, stderr
VSingleType::Tuple(vec![ VSingleType::Tuple(vec![
VType { VType {
@ -454,7 +465,7 @@ impl BuiltinFunction {
Self::RunCommandGetBytes => VType { Self::RunCommandGetBytes => VType {
types: vec![ types: vec![
// error // error
VSingleType::String.into(), VSingleType::EnumVariant(EV_ERR, VSingleType::String.to()),
// success: Option<ExitCode>, stdout, stderr // success: Option<ExitCode>, stdout, stderr
VSingleType::Tuple(vec![ VSingleType::Tuple(vec![
VType { VType {
@ -502,18 +513,10 @@ impl BuiltinFunction {
Self::Substring => VSingleType::String.into(), Self::Substring => VSingleType::String.into(),
Self::Regex => VType { Self::Regex => VType {
types: vec![ types: vec![
VSingleType::Tuple(vec![ // [string ...]
// does match VSingleType::List(VSingleType::String.to()),
VSingleType::Tuple(vec![VSingleType::List(VSingleType::String.to()).to()]) // Err(string)
.to(), VSingleType::EnumVariant(EV_ERR, VSingleType::String.to()),
// no error
]),
VSingleType::Tuple(vec![
// does not match
VSingleType::Tuple(vec![]).to(),
// error
VSingleType::String.to(),
]),
], ],
}, },
} }
@ -525,9 +528,10 @@ impl BuiltinFunction {
libs: &Arc<Vec<libs::Lib>>, libs: &Arc<Vec<libs::Lib>>,
) -> VData { ) -> VData {
match self { match self {
Self::Assume1 => { Self::Assume1 => match args[0].run(vars, libs).data {
if let VDataEnum::Tuple(mut v) = args[0].run(vars, libs).data { VDataEnum::Tuple(mut v) => {
v.pop().unwrap() if let Some(v) = v.pop() {
v
} else { } else {
panic!( panic!(
"ASSUMPTION FAILED: assume1 :: {}", "ASSUMPTION FAILED: assume1 :: {}",
@ -543,7 +547,13 @@ impl BuiltinFunction {
); );
} }
} }
v => v.to(),
},
Self::NoEnum => args[0].run(vars, libs).noenum(), 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 => { BuiltinFunction::Print => {
if let VDataEnum::String(arg) = args[0].run(vars, libs).data { if let VDataEnum::String(arg) = args[0].run(vars, libs).data {
print!("{}", arg); print!("{}", arg);
@ -704,8 +714,8 @@ impl BuiltinFunction {
if args.len() > 1 { if args.len() > 1 {
todo!("fs_list advanced filters") todo!("fs_list advanced filters")
} }
if let Ok(entries) = std::fs::read_dir(path) { match std::fs::read_dir(path) {
VDataEnum::List( Ok(entries) => VDataEnum::List(
VSingleType::String.into(), VSingleType::String.into(),
entries entries
.filter_map(|entry| { .filter_map(|entry| {
@ -722,9 +732,12 @@ impl BuiltinFunction {
}) })
.collect(), .collect(),
) )
.to() .to(),
} else { Err(e) => VDataEnum::EnumVariant(
VDataEnum::Tuple(vec![]).to() EV_ERR,
Box::new(VDataEnum::String(e.to_string()).to()),
)
.to(),
} }
} else { } else {
unreachable!("fs_list first arg not a string") unreachable!("fs_list first arg not a string")
@ -736,16 +749,19 @@ impl BuiltinFunction {
Self::FsRead => { Self::FsRead => {
if args.len() > 0 { if args.len() > 0 {
if let VDataEnum::String(path) = args[0].run(vars, libs).data { if let VDataEnum::String(path) = args[0].run(vars, libs).data {
if let Ok(data) = std::fs::read(path) { match std::fs::read(path) {
VDataEnum::List( Ok(data) => VDataEnum::List(
VSingleType::Int.into(), VSingleType::Int.into(),
data.into_iter() data.into_iter()
.map(|v| VDataEnum::Int(v as _).to()) .map(|v| VDataEnum::Int(v as _).to())
.collect(), .collect(),
) )
.to() .to(),
} else { Err(e) => VDataEnum::EnumVariant(
VDataEnum::Tuple(vec![]).to() EV_ERR,
Box::new(VDataEnum::String(e.to_string()).to()),
)
.to(),
} }
} else { } else {
unreachable!("fs_read first arg not a string") unreachable!("fs_read first arg not a string")
@ -766,7 +782,11 @@ impl BuiltinFunction {
} }
match std::fs::write(file_path, bytes) { match std::fs::write(file_path, bytes) {
Ok(_) => VDataEnum::Tuple(vec![]).to(), 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 { } else {
unreachable!( unreachable!(
@ -788,13 +808,20 @@ impl BuiltinFunction {
Ok(v) => VDataEnum::String(v).to(), Ok(v) => VDataEnum::String(v).to(),
Err(e) => { Err(e) => {
let err = e.to_string(); let err = e.to_string();
VDataEnum::EnumVariant(
EV_ERR,
Box::new(
VDataEnum::Tuple(vec![ VDataEnum::Tuple(vec![
VDataEnum::String( VDataEnum::String(
String::from_utf8_lossy(&e.into_bytes()).into_owned(), String::from_utf8_lossy(&e.into_bytes())
.into_owned(),
) )
.to(), .to(),
VDataEnum::String(err).to(), VDataEnum::String(err).to(),
]) ])
.to(),
),
)
.to() .to()
} }
} }
@ -876,7 +903,11 @@ impl BuiltinFunction {
.to(), .to(),
]) ])
.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 { } else {
unreachable!("run_command not string arg") unreachable!("run_command not string arg")
@ -1345,11 +1376,17 @@ impl BuiltinFunction {
.to()]) .to()])
.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::Tuple(vec![]).to(), // no results
VDataEnum::String(e.to_string()).to(), VDataEnum::String(e.to_string()).to(),
]) ])
.to(), .to(),
),
)
.to(),
} }
} else { } else {
unreachable!() unreachable!()

View File

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