mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
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:
parent
b1a90d5872
commit
794e776e25
13
enums.txt
13
enums.txt
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
po.0
|
||||
})
|
||||
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 => {
|
||||
|
@ -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;
|
||||
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());
|
||||
fn make_readable(v: &mut VType, ginfo: &GInfo) {
|
||||
for t in v.types.iter_mut() {
|
||||
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})"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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::Tuple(vec![
|
||||
VSingleType::String.into(), // lossy string
|
||||
VSingleType::String.into(), // error message
|
||||
])
|
||||
.into(),
|
||||
VSingleType::String,
|
||||
VSingleType::EnumVariant(
|
||||
EV_ERR,
|
||||
VSingleType::Tuple(vec![
|
||||
VSingleType::String.into(), // lossy string
|
||||
VSingleType::String.into(), // error message
|
||||
])
|
||||
.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,25 +528,32 @@ 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()
|
||||
} else {
|
||||
panic!(
|
||||
"ASSUMPTION FAILED: assume1 :: {}",
|
||||
if args.len() > 1 {
|
||||
if let VDataEnum::String(v) = args[1].run(vars, libs).data {
|
||||
v
|
||||
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 :: {}",
|
||||
if args.len() > 1 {
|
||||
if let VDataEnum::String(v) = args[1].run(vars, libs).data {
|
||||
v
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
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::Tuple(vec![
|
||||
VDataEnum::String(
|
||||
String::from_utf8_lossy(&e.into_bytes()).into_owned(),
|
||||
)
|
||||
.to(),
|
||||
VDataEnum::String(err).to(),
|
||||
])
|
||||
VDataEnum::EnumVariant(
|
||||
EV_ERR,
|
||||
Box::new(
|
||||
VDataEnum::Tuple(vec![
|
||||
VDataEnum::String(
|
||||
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,10 +1376,16 @@ impl BuiltinFunction {
|
||||
.to()])
|
||||
.to()
|
||||
}
|
||||
Err(e) => VDataEnum::Tuple(vec![
|
||||
VDataEnum::Tuple(vec![]).to(), // no results
|
||||
VDataEnum::String(e.to_string()).to(),
|
||||
])
|
||||
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 {
|
||||
|
@ -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()),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user