mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
completely changed the VData/VDataEnum system: Multiple VData can share one VDataEnum via an Arc<Mutex<VDataEnum>>. If one wants to modify the data, it copies it (Copy on Write). This copying is skipped for shared mutable data (references). This was necessary for the get_ref() function. Expect bugs!
This commit is contained in:
parent
ceddb886a9
commit
4efee9e2a2
8
get_ref.mers
Normal file
8
get_ref.mers
Normal file
@ -0,0 +1,8 @@
|
||||
list = [1 2 3 4 5 6 7 8 9 ...]
|
||||
|
||||
second = &list.get_ref(2).assume1()
|
||||
second.debug()
|
||||
*second = 24
|
||||
second.debug()
|
||||
|
||||
list.debug()
|
@ -461,7 +461,7 @@ impl ByteData for VSingleType {
|
||||
}
|
||||
impl ByteDataA for VData {
|
||||
fn as_byte_data(&self, vec: &mut Vec<u8>) {
|
||||
self.data.as_byte_data(vec)
|
||||
self.data().0.as_byte_data(vec)
|
||||
}
|
||||
}
|
||||
impl ByteData for VData {
|
||||
@ -469,9 +469,7 @@ impl ByteData for VData {
|
||||
where
|
||||
R: std::io::Read,
|
||||
{
|
||||
Ok(Self {
|
||||
data: ByteData::from_byte_data(data)?,
|
||||
})
|
||||
Ok(VDataEnum::from_byte_data(data)?.to())
|
||||
}
|
||||
}
|
||||
impl ByteDataA for VDataEnum {
|
||||
|
@ -910,8 +910,8 @@ pub mod implementation {
|
||||
let args = [out].into_iter().chain(args.into_iter()).collect();
|
||||
SStatementEnum::FunctionCall(func, args).to()
|
||||
}
|
||||
SStatementEnum::Value(vd) => match vd.data {
|
||||
VDataEnum::Int(i) => SStatementEnum::IndexFixed(out, i as _).to(),
|
||||
SStatementEnum::Value(vd) => match &vd.data().0 {
|
||||
VDataEnum::Int(i) => SStatementEnum::IndexFixed(out, *i as _).to(),
|
||||
_ => {
|
||||
let mut context = vec![];
|
||||
if chain_length > 0 {
|
||||
|
@ -76,6 +76,7 @@ pub enum BuiltinFunction {
|
||||
Pop,
|
||||
Remove,
|
||||
Get,
|
||||
GetRef,
|
||||
Len,
|
||||
// String
|
||||
Contains,
|
||||
@ -138,6 +139,7 @@ impl BuiltinFunction {
|
||||
"pop" => Self::Pop,
|
||||
"remove" => Self::Remove,
|
||||
"get" => Self::Get,
|
||||
"get_ref" => Self::GetRef,
|
||||
"len" => Self::Len,
|
||||
"contains" => Self::Contains,
|
||||
"starts_with" => Self::StartsWith,
|
||||
@ -443,7 +445,7 @@ impl BuiltinFunction {
|
||||
}
|
||||
}
|
||||
// TODO! finish this
|
||||
Self::Get | Self::Len => true,
|
||||
Self::Get | Self::GetRef | Self::Len => true,
|
||||
Self::Substring => {
|
||||
if input.len() >= 2 && input.len() <= 3 {
|
||||
let (s, start) = (&input[0], &input[1]);
|
||||
@ -598,6 +600,26 @@ impl BuiltinFunction {
|
||||
unreachable!("get, pop or remove called without args")
|
||||
}
|
||||
}
|
||||
Self::GetRef => {
|
||||
if let Some(v) = input.first() {
|
||||
VType {
|
||||
types: vec![
|
||||
VSingleType::Tuple(vec![]),
|
||||
VSingleType::Tuple(vec![{
|
||||
let mut v = v.get_any(info).expect("cannot use get on this type");
|
||||
v.types = v
|
||||
.types
|
||||
.into_iter()
|
||||
.map(|v| VSingleType::Reference(Box::new(v)))
|
||||
.collect();
|
||||
v
|
||||
}]),
|
||||
],
|
||||
}
|
||||
} else {
|
||||
unreachable!("get, pop or remove called without args")
|
||||
}
|
||||
}
|
||||
Self::Exit => VType { types: vec![] }, // doesn't return
|
||||
Self::FsList => VType {
|
||||
types: vec![
|
||||
@ -726,67 +748,87 @@ impl BuiltinFunction {
|
||||
},
|
||||
}
|
||||
}
|
||||
pub fn run(
|
||||
&self,
|
||||
args: &Vec<RStatement>,
|
||||
vars: &Vec<Arc<Mutex<VData>>>,
|
||||
info: &GSInfo,
|
||||
) -> VData {
|
||||
pub fn run(&self, args: &Vec<RStatement>, vars: &mut Vec<VData>, info: &GSInfo) -> VData {
|
||||
match self {
|
||||
Self::Assume1 => match args[0].run(vars, info).data {
|
||||
VDataEnum::Tuple(mut v) => {
|
||||
Self::Assume1 => {
|
||||
let mut a0 = args[0].run(vars, info);
|
||||
a0.make_mut();
|
||||
let o = match &mut a0.data.lock().unwrap().0 {
|
||||
VDataEnum::Tuple(v) => Some({
|
||||
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, info).data {
|
||||
v
|
||||
let msg = if args.len() > 1 {
|
||||
let a1 = args[1].run(vars, info);
|
||||
let a1 = a1.data();
|
||||
if let VDataEnum::String(v) = &a1.0 {
|
||||
Some(v.to_owned())
|
||||
} else {
|
||||
String::new()
|
||||
None
|
||||
}
|
||||
} else {
|
||||
String::new()
|
||||
},
|
||||
);
|
||||
None
|
||||
};
|
||||
if let Some(m) = msg {
|
||||
panic!("ASSUMPTION FAILED: assume1 :: {m}");
|
||||
} else {
|
||||
panic!("ASSUMPTION FAILED: assume1");
|
||||
}
|
||||
}
|
||||
}),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(o) = o {
|
||||
o
|
||||
} else {
|
||||
a0
|
||||
}
|
||||
}
|
||||
v => v.to(),
|
||||
},
|
||||
Self::AssumeNoEnum => {
|
||||
let data = args[0].run(vars, info);
|
||||
match data.data {
|
||||
VDataEnum::EnumVariant(..) => panic!(
|
||||
"ASSUMPTION FAILED: assume_no_enum :: found {} :: {}",
|
||||
data.gsi(info.clone()),
|
||||
if args.len() > 1 {
|
||||
if let VDataEnum::String(v) = args[1].run(vars, info).data {
|
||||
v
|
||||
let msg = if args.len() > 1 {
|
||||
if let VDataEnum::String(v) = args[1].run(vars, info).inner() {
|
||||
Some(v.to_owned())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let a0 = args[0].run(vars, info);
|
||||
let a0d = a0.data();
|
||||
match &a0d.0 {
|
||||
VDataEnum::EnumVariant(..) => {
|
||||
drop(a0d);
|
||||
panic!(
|
||||
"ASSUMPTION FAILED: assume_no_enum :: found {}{}",
|
||||
a0.gsi(info.clone()),
|
||||
if let Some(m) = msg {
|
||||
format!(" :: {m}")
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
} else {
|
||||
String::new()
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
drop(a0d);
|
||||
a0
|
||||
}
|
||||
),
|
||||
d => d.to(),
|
||||
}
|
||||
}
|
||||
Self::NoEnum => args[0].run(vars, info).noenum(),
|
||||
Self::Matches => match args[0].run(vars, info).data.matches() {
|
||||
Self::Matches => match args[0].run(vars, info).inner().matches() {
|
||||
Some(v) => VDataEnum::Tuple(vec![v]).to(),
|
||||
None => VDataEnum::Tuple(vec![]).to(),
|
||||
},
|
||||
Self::Clone => {
|
||||
if let VDataEnum::Reference(r) = args[0].run(vars, info).data {
|
||||
r.lock().unwrap().clone()
|
||||
if let VDataEnum::Reference(r) = &args[0].run(vars, info).data().0 {
|
||||
r.clone()
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
BuiltinFunction::Print => {
|
||||
if let VDataEnum::String(arg) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::String(arg) = &args[0].run(vars, info).data().0 {
|
||||
print!("{}", arg);
|
||||
VDataEnum::Tuple(vec![]).to()
|
||||
} else {
|
||||
@ -794,7 +836,7 @@ impl BuiltinFunction {
|
||||
}
|
||||
}
|
||||
BuiltinFunction::Println => {
|
||||
if let VDataEnum::String(arg) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::String(arg) = &args[0].run(vars, info).data().0 {
|
||||
#[cfg(not(feature = "nushell_plugin"))]
|
||||
println!("{}", arg);
|
||||
#[cfg(feature = "nushell_plugin")]
|
||||
@ -831,13 +873,13 @@ impl BuiltinFunction {
|
||||
VDataEnum::String(args[0].run(vars, info).gsi(info.clone()).to_string()).to()
|
||||
}
|
||||
BuiltinFunction::Format => {
|
||||
if let VDataEnum::String(mut text) = args.first().unwrap().run(vars, info).data {
|
||||
if let VDataEnum::String(mut text) = args.first().unwrap().run(vars, info).inner() {
|
||||
for (i, arg) in args.iter().skip(1).enumerate() {
|
||||
text = text.replace(
|
||||
&format!("{{{i}}}"),
|
||||
&format!(
|
||||
"{}",
|
||||
if let VDataEnum::String(v) = arg.run(vars, info).data {
|
||||
if let VDataEnum::String(v) = &arg.run(vars, info).data().0 {
|
||||
v
|
||||
} else {
|
||||
unreachable!()
|
||||
@ -852,7 +894,7 @@ impl BuiltinFunction {
|
||||
}
|
||||
BuiltinFunction::ParseInt => {
|
||||
if args.len() == 1 {
|
||||
if let VDataEnum::String(s) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::String(s) = &args[0].run(vars, info).data().0 {
|
||||
if let Ok(s) = s.parse() {
|
||||
VDataEnum::Int(s).to()
|
||||
} else {
|
||||
@ -867,7 +909,7 @@ impl BuiltinFunction {
|
||||
}
|
||||
BuiltinFunction::ParseFloat => {
|
||||
if args.len() == 1 {
|
||||
if let VDataEnum::String(s) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::String(s) = &args[0].run(vars, info).data().0 {
|
||||
if let Ok(s) = s.parse() {
|
||||
VDataEnum::Float(s).to()
|
||||
} else {
|
||||
@ -882,13 +924,13 @@ impl BuiltinFunction {
|
||||
}
|
||||
BuiltinFunction::Run => {
|
||||
if args.len() >= 1 {
|
||||
if let VDataEnum::Function(f) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::Function(f) = &args[0].run(vars, info).data().0 {
|
||||
if f.inputs.len() != args.len() - 1 {
|
||||
unreachable!()
|
||||
}
|
||||
for (i, var) in f.inputs.iter().enumerate() {
|
||||
let val = args[i + 1].run(vars, info);
|
||||
*vars[*var].lock().unwrap() = val;
|
||||
vars[*var] = val;
|
||||
}
|
||||
f.run(vars, info)
|
||||
} else {
|
||||
@ -900,7 +942,7 @@ impl BuiltinFunction {
|
||||
}
|
||||
BuiltinFunction::Thread => {
|
||||
if args.len() >= 1 {
|
||||
if let VDataEnum::Function(f) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::Function(f) = args[0].run(vars, info).inner() {
|
||||
if f.inputs.len() != args.len() - 1 {
|
||||
unreachable!()
|
||||
}
|
||||
@ -910,13 +952,13 @@ impl BuiltinFunction {
|
||||
for (i, var) in f.inputs.iter().enumerate() {
|
||||
let val = args[i + 1].run(vars, info);
|
||||
run_input_types.push(val.out_single());
|
||||
thread_vars[*var] = Arc::new(Mutex::new(val));
|
||||
thread_vars[*var] = val;
|
||||
}
|
||||
let out_type = f.out(&run_input_types);
|
||||
let libs = info.clone();
|
||||
VDataEnum::Thread(
|
||||
VDataThreadEnum::Running(std::thread::spawn(move || {
|
||||
f.run(&thread_vars, &libs)
|
||||
f.run(&mut thread_vars, &libs)
|
||||
}))
|
||||
.to(),
|
||||
out_type,
|
||||
@ -931,7 +973,7 @@ impl BuiltinFunction {
|
||||
}
|
||||
BuiltinFunction::Await => {
|
||||
if args.len() == 1 {
|
||||
if let VDataEnum::Thread(t, _) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::Thread(t, _) = &args[0].run(vars, info).data().0 {
|
||||
t.get()
|
||||
} else {
|
||||
unreachable!()
|
||||
@ -942,9 +984,9 @@ impl BuiltinFunction {
|
||||
}
|
||||
BuiltinFunction::Sleep => {
|
||||
if args.len() == 1 {
|
||||
match args[0].run(vars, info).data {
|
||||
VDataEnum::Int(v) => std::thread::sleep(Duration::from_secs(v as _)),
|
||||
VDataEnum::Float(v) => std::thread::sleep(Duration::from_secs_f64(v)),
|
||||
match &args[0].run(vars, info).data().0 {
|
||||
VDataEnum::Int(v) => std::thread::sleep(Duration::from_secs(*v as _)),
|
||||
VDataEnum::Float(v) => std::thread::sleep(Duration::from_secs_f64(*v)),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
VDataEnum::Tuple(vec![]).to()
|
||||
@ -954,8 +996,8 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Exit => {
|
||||
if let Some(s) = args.first() {
|
||||
if let VDataEnum::Int(v) = s.run(vars, info).data {
|
||||
std::process::exit(v as _);
|
||||
if let VDataEnum::Int(v) = &s.run(vars, info).data().0 {
|
||||
std::process::exit(*v as _);
|
||||
} else {
|
||||
std::process::exit(1);
|
||||
}
|
||||
@ -965,7 +1007,7 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::FsList => {
|
||||
if args.len() > 0 {
|
||||
if let VDataEnum::String(path) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::String(path) = &args[0].run(vars, info).data().0 {
|
||||
if args.len() > 1 {
|
||||
eprintln!("NOT YET IMPLEMENTED (TODO!): fs_list advanced filters")
|
||||
}
|
||||
@ -1003,7 +1045,7 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::FsRead => {
|
||||
if args.len() > 0 {
|
||||
if let VDataEnum::String(path) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::String(path) = &args[0].run(vars, info).data().0 {
|
||||
match std::fs::read(path) {
|
||||
Ok(data) => VDataEnum::List(
|
||||
VSingleType::Int.into(),
|
||||
@ -1027,9 +1069,10 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::FsWrite => {
|
||||
if args.len() > 1 {
|
||||
if let (VDataEnum::String(path), VDataEnum::List(_, data)) =
|
||||
(args[0].run(vars, info).data, args[1].run(vars, info).data)
|
||||
{
|
||||
if let (VDataEnum::String(path), VDataEnum::List(_, data)) = (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
) {
|
||||
if let Some(bytes) = vdata_to_bytes(&data) {
|
||||
let file_path: PathBuf = path.into();
|
||||
if let Some(p) = file_path.parent() {
|
||||
@ -1057,7 +1100,7 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::BytesToString => {
|
||||
if args.len() == 1 {
|
||||
if let VDataEnum::List(_, byte_data) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::List(_, byte_data) = &args[0].run(vars, info).data().0 {
|
||||
if let Some(bytes) = vdata_to_bytes(&byte_data) {
|
||||
match String::from_utf8(bytes) {
|
||||
Ok(v) => VDataEnum::String(v).to(),
|
||||
@ -1092,7 +1135,7 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::StringToBytes => {
|
||||
if args.len() == 1 {
|
||||
if let VDataEnum::String(s) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::String(s) = &args[0].run(vars, info).data().0 {
|
||||
VDataEnum::List(
|
||||
VSingleType::Int.into(),
|
||||
s.bytes().map(|v| VDataEnum::Int(v as isize).to()).collect(),
|
||||
@ -1107,12 +1150,12 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::RunCommand | Self::RunCommandGetBytes => {
|
||||
if args.len() > 0 {
|
||||
if let VDataEnum::String(s) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::String(s) = &args[0].run(vars, info).data().0 {
|
||||
let mut command = std::process::Command::new(s);
|
||||
if args.len() > 1 {
|
||||
if let VDataEnum::List(_, args) = args[1].run(vars, info).data {
|
||||
if let VDataEnum::List(_, args) = &args[1].run(vars, info).data().0 {
|
||||
for arg in args {
|
||||
if let VDataEnum::String(v) = arg.data {
|
||||
if let VDataEnum::String(v) = &arg.data().0 {
|
||||
command.arg(v);
|
||||
} else {
|
||||
unreachable!("run_command second arg not [string].")
|
||||
@ -1172,19 +1215,19 @@ impl BuiltinFunction {
|
||||
}
|
||||
}
|
||||
Self::Not => {
|
||||
if let VDataEnum::Bool(v) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::Bool(v) = &args[0].run(vars, info).data().0 {
|
||||
VDataEnum::Bool(!v).to()
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
Self::And => {
|
||||
if let VDataEnum::Bool(a) = args[0].run(vars, info).data {
|
||||
if a == false {
|
||||
if let VDataEnum::Bool(a) = &args[0].run(vars, info).data().0 {
|
||||
if *a == false {
|
||||
VDataEnum::Bool(false).to()
|
||||
} else {
|
||||
if let VDataEnum::Bool(b) = args[1].run(vars, info).data {
|
||||
VDataEnum::Bool(b).to()
|
||||
if let VDataEnum::Bool(b) = &args[1].run(vars, info).data().0 {
|
||||
VDataEnum::Bool(*b).to()
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
@ -1194,12 +1237,12 @@ impl BuiltinFunction {
|
||||
}
|
||||
}
|
||||
Self::Or => {
|
||||
if let VDataEnum::Bool(a) = args[0].run(vars, info).data {
|
||||
if a == true {
|
||||
if let VDataEnum::Bool(a) = &args[0].run(vars, info).data().0 {
|
||||
if *a == true {
|
||||
VDataEnum::Bool(true).to()
|
||||
} else {
|
||||
if let VDataEnum::Bool(b) = args[1].run(vars, info).data {
|
||||
VDataEnum::Bool(b).to()
|
||||
if let VDataEnum::Bool(b) = &args[1].run(vars, info).data().0 {
|
||||
VDataEnum::Bool(*b).to()
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
@ -1210,7 +1253,10 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Add => {
|
||||
if args.len() == 2 {
|
||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
||||
match (
|
||||
args[0].run(vars, info).inner(),
|
||||
args[1].run(vars, info).inner(),
|
||||
) {
|
||||
(VDataEnum::String(mut a), VDataEnum::String(b)) => {
|
||||
a.push_str(b.as_str());
|
||||
VDataEnum::String(a).to()
|
||||
@ -1231,13 +1277,16 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Sub => {
|
||||
if args.len() == 2 {
|
||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
||||
match (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a - b).to(),
|
||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||
VDataEnum::Float(a as f64 - b).to()
|
||||
VDataEnum::Float(*a as f64 - *b).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||
VDataEnum::Float(a - b as f64).to()
|
||||
VDataEnum::Float(*a - *b as f64).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a - b).to(),
|
||||
_ => unreachable!("sub: not a number"),
|
||||
@ -1248,13 +1297,16 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Mul => {
|
||||
if args.len() == 2 {
|
||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
||||
match (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a * b).to(),
|
||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||
VDataEnum::Float(a as f64 * b).to()
|
||||
VDataEnum::Float(*a as f64 * b).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||
VDataEnum::Float(a * b as f64).to()
|
||||
VDataEnum::Float(a * *b as f64).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a * b).to(),
|
||||
_ => unreachable!("mul: not a number"),
|
||||
@ -1265,13 +1317,16 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Div => {
|
||||
if args.len() == 2 {
|
||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
||||
match (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a / b).to(),
|
||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||
VDataEnum::Float(a as f64 / b).to()
|
||||
VDataEnum::Float(*a as f64 / b).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||
VDataEnum::Float(a / b as f64).to()
|
||||
VDataEnum::Float(a / *b as f64).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a / b).to(),
|
||||
_ => unreachable!("div: not a number"),
|
||||
@ -1282,13 +1337,16 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Mod => {
|
||||
if args.len() == 2 {
|
||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
||||
match (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a % b).to(),
|
||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||
VDataEnum::Float(a as f64 % b).to()
|
||||
VDataEnum::Float(*a as f64 % b).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||
VDataEnum::Float(a % b as f64).to()
|
||||
VDataEnum::Float(a % *b as f64).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a % b).to(),
|
||||
_ => unreachable!("mod: not a number"),
|
||||
@ -1299,23 +1357,26 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Pow => {
|
||||
if args.len() == 2 {
|
||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(if b == 0 {
|
||||
match (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(if *b == 0 {
|
||||
1
|
||||
} else if b > 0 {
|
||||
a.pow(b as _)
|
||||
} else if *b > 0 {
|
||||
(*a).pow(*b as _)
|
||||
} else {
|
||||
0
|
||||
})
|
||||
.to(),
|
||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||
VDataEnum::Float((a as f64).powf(b)).to()
|
||||
VDataEnum::Float((*a as f64).powf(*b)).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||
VDataEnum::Float(a.powi(b as _)).to()
|
||||
VDataEnum::Float((*a).powi(*b as _)).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => {
|
||||
VDataEnum::Float(a.powf(b)).to()
|
||||
VDataEnum::Float((*a).powf(*b)).to()
|
||||
}
|
||||
_ => unreachable!("pow: not a number"),
|
||||
}
|
||||
@ -1332,15 +1393,18 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Gt => {
|
||||
if args.len() == 2 {
|
||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a > b).to(),
|
||||
match (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(*a > *b).to(),
|
||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||
VDataEnum::Bool(a as f64 > b).to()
|
||||
VDataEnum::Bool(*a as f64 > *b).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||
VDataEnum::Bool(a > b as f64).to()
|
||||
VDataEnum::Bool(*a > *b as f64).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Bool(a > b).to(),
|
||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Bool(*a > *b).to(),
|
||||
_ => unreachable!("gt: not a number"),
|
||||
}
|
||||
} else {
|
||||
@ -1349,15 +1413,18 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Lt => {
|
||||
if args.len() == 2 {
|
||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a < b).to(),
|
||||
match (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(*a < *b).to(),
|
||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||
VDataEnum::Bool((a as f64) < b).to()
|
||||
VDataEnum::Bool((*a as f64) < *b).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||
VDataEnum::Bool(a < b as f64).to()
|
||||
VDataEnum::Bool(*a < *b as f64).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Bool(a < b).to(),
|
||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Bool(*a < *b).to(),
|
||||
_ => unreachable!("lt: not a number"),
|
||||
}
|
||||
} else {
|
||||
@ -1366,15 +1433,20 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Gtoe => {
|
||||
if args.len() == 2 {
|
||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a >= b).to(),
|
||||
match (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(*a >= *b).to(),
|
||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||
VDataEnum::Bool(a as f64 >= b).to()
|
||||
VDataEnum::Bool(*a as f64 >= *b).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||
VDataEnum::Bool(a >= b as f64).to()
|
||||
VDataEnum::Bool(*a >= *b as f64).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => {
|
||||
VDataEnum::Bool(*a >= *b).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Bool(a >= b).to(),
|
||||
_ => unreachable!("gtoe: not a number"),
|
||||
}
|
||||
} else {
|
||||
@ -1383,15 +1455,20 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Ltoe => {
|
||||
if args.len() == 2 {
|
||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a <= b).to(),
|
||||
match (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(*a <= *b).to(),
|
||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||
VDataEnum::Bool(a as f64 <= b).to()
|
||||
VDataEnum::Bool(*a as f64 <= *b).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||
VDataEnum::Bool(a <= b as f64).to()
|
||||
VDataEnum::Bool(*a <= *b as f64).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => {
|
||||
VDataEnum::Bool(*a <= *b).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Bool(a <= b).to(),
|
||||
_ => unreachable!("ltoe: not a number"),
|
||||
}
|
||||
} else {
|
||||
@ -1400,16 +1477,19 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Min => {
|
||||
if args.len() == 2 {
|
||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a.min(b)).to(),
|
||||
match (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int((*a).min(*b)).to(),
|
||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||
VDataEnum::Float((a as f64).min(b)).to()
|
||||
VDataEnum::Float((*a as f64).min(*b)).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||
VDataEnum::Float(a.min(b as f64)).to()
|
||||
VDataEnum::Float((*a).min(*b as f64)).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => {
|
||||
VDataEnum::Float(a.min(b)).to()
|
||||
VDataEnum::Float((*a).min(*b)).to()
|
||||
}
|
||||
_ => unreachable!("min: not a number"),
|
||||
}
|
||||
@ -1419,16 +1499,19 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Max => {
|
||||
if args.len() == 2 {
|
||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a.max(b)).to(),
|
||||
match (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
) {
|
||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int((*a).max(*b)).to(),
|
||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||
VDataEnum::Float((a as f64).max(b)).to()
|
||||
VDataEnum::Float((*a as f64).max(*b)).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||
VDataEnum::Float(a.max(b as f64)).to()
|
||||
VDataEnum::Float((*a).max(*b as f64)).to()
|
||||
}
|
||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => {
|
||||
VDataEnum::Float(a.max(b)).to()
|
||||
VDataEnum::Float((*a).max(*b)).to()
|
||||
}
|
||||
_ => unreachable!("max: not a number"),
|
||||
}
|
||||
@ -1438,8 +1521,9 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Push => {
|
||||
if args.len() == 2 {
|
||||
if let VDataEnum::Reference(v) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
||||
// Since this is a reference, it is safe to assume that make_mut() would do nothing.
|
||||
if let VDataEnum::Reference(v) = &args[0].run(vars, info).data().0 {
|
||||
if let VDataEnum::List(_, v) = &mut v.data().0 {
|
||||
v.push(args[1].run(vars, info));
|
||||
}
|
||||
VDataEnum::Tuple(vec![]).to()
|
||||
@ -1452,11 +1536,13 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Insert => {
|
||||
if args.len() == 3 {
|
||||
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) =
|
||||
(args[0].run(vars, info).data, args[2].run(vars, info).data)
|
||||
{
|
||||
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
||||
v.insert(i as _, args[1].run(vars, info));
|
||||
// this being a reference means we wont need to call make_mut() later, so a .as_ref() borrow is enough.
|
||||
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) = (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[2].run(vars, info).data().0,
|
||||
) {
|
||||
if let VDataEnum::List(_, v) = &mut v.data().0 {
|
||||
v.insert(*i as _, args[1].run(vars, info));
|
||||
}
|
||||
VDataEnum::Tuple(vec![]).to()
|
||||
} else {
|
||||
@ -1468,8 +1554,9 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Pop => {
|
||||
if args.len() == 1 {
|
||||
if let VDataEnum::Reference(v) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
||||
// this being a reference means we wont need to call make_mut() later, so a .as_ref() borrow is enough.
|
||||
if let VDataEnum::Reference(v) = &args[0].run(vars, info).data().0 {
|
||||
if let VDataEnum::List(_, v) = &mut v.data.lock().unwrap().0 {
|
||||
if let Some(v) = v.pop() {
|
||||
VDataEnum::Tuple(vec![v])
|
||||
} else {
|
||||
@ -1488,12 +1575,14 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Remove => {
|
||||
if args.len() == 2 {
|
||||
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) =
|
||||
(args[0].run(vars, info).data, args[1].run(vars, info).data)
|
||||
{
|
||||
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
||||
if v.len() > i as _ && i >= 0 {
|
||||
let v = v.remove(i as _);
|
||||
// this being a reference means we wont need to call make_mut() later, so a .as_ref() borrow is enough.
|
||||
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) = (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
) {
|
||||
if let VDataEnum::List(_, v) = &mut v.data.lock().unwrap().0 {
|
||||
if *i >= 0 && v.len() > *i as _ {
|
||||
let v = v.remove(*i as _);
|
||||
VDataEnum::Tuple(vec![v]).to()
|
||||
} else {
|
||||
VDataEnum::Tuple(vec![]).to()
|
||||
@ -1510,21 +1599,22 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Get => {
|
||||
if args.len() == 2 {
|
||||
if let (container, VDataEnum::Int(i)) =
|
||||
(args[0].run(vars, info).data, args[1].run(vars, info).data)
|
||||
{
|
||||
if i >= 0 {
|
||||
if let (container, VDataEnum::Int(i)) = (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
) {
|
||||
if *i >= 0 {
|
||||
match match container {
|
||||
VDataEnum::Reference(v) => match &v.lock().unwrap().data {
|
||||
VDataEnum::Reference(v) => match &v.data().0 {
|
||||
VDataEnum::List(_, v) | VDataEnum::Tuple(v) => {
|
||||
v.get(i as usize).map(|v| v.clone())
|
||||
v.get(*i as usize).map(|v| v.clone())
|
||||
}
|
||||
_ => unreachable!(
|
||||
"get: reference to something other than list/tuple"
|
||||
),
|
||||
},
|
||||
VDataEnum::List(_, v) | VDataEnum::Tuple(v) => {
|
||||
v.get(i as usize).map(|v| v.clone())
|
||||
v.get(*i as usize).map(|v| v.clone())
|
||||
}
|
||||
_ => unreachable!("get: not a reference/list/tuple"),
|
||||
} {
|
||||
@ -1541,9 +1631,40 @@ impl BuiltinFunction {
|
||||
unreachable!("get: not 2 args")
|
||||
}
|
||||
}
|
||||
Self::GetRef => {
|
||||
if args.len() == 2 {
|
||||
if let (VDataEnum::Reference(container), VDataEnum::Int(i)) = (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
) {
|
||||
if *i >= 0 {
|
||||
// we can get mutably because this is the content of a reference
|
||||
match match &mut container.data().0 {
|
||||
VDataEnum::List(_, v) | VDataEnum::Tuple(v) => {
|
||||
if let Some(v) = v.get_mut(*i as usize) {
|
||||
Some(VDataEnum::Reference(v.clone_mut()).to())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => unreachable!("get: not a reference/list/tuple"),
|
||||
} {
|
||||
Some(v) => VDataEnum::Tuple(vec![v]).to(),
|
||||
None => VDataEnum::Tuple(vec![]).to(),
|
||||
}
|
||||
} else {
|
||||
VDataEnum::Tuple(vec![]).to()
|
||||
}
|
||||
} else {
|
||||
unreachable!("get_ref: not a reference and index")
|
||||
}
|
||||
} else {
|
||||
unreachable!("get: not 2 args")
|
||||
}
|
||||
}
|
||||
Self::Len => {
|
||||
if args.len() == 1 {
|
||||
VDataEnum::Int(match args[0].run(vars, info).data {
|
||||
VDataEnum::Int(match &args[0].run(vars, info).data().0 {
|
||||
VDataEnum::String(v) => v.len(),
|
||||
VDataEnum::Tuple(v) => v.len(),
|
||||
VDataEnum::List(_, v) => v.len(),
|
||||
@ -1556,8 +1677,8 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Contains => {
|
||||
if args.len() == 2 {
|
||||
if let VDataEnum::String(a1) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::String(a2) = args[1].run(vars, info).data {
|
||||
if let VDataEnum::String(a1) = &args[0].run(vars, info).data().0 {
|
||||
if let VDataEnum::String(a2) = &args[1].run(vars, info).data().0 {
|
||||
VDataEnum::Bool(a1.contains(a2.as_str())).to()
|
||||
} else {
|
||||
unreachable!()
|
||||
@ -1571,8 +1692,8 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::StartsWith => {
|
||||
if args.len() == 2 {
|
||||
if let VDataEnum::String(a1) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::String(a2) = args[1].run(vars, info).data {
|
||||
if let VDataEnum::String(a1) = &args[0].run(vars, info).data().0 {
|
||||
if let VDataEnum::String(a2) = &args[1].run(vars, info).data().0 {
|
||||
VDataEnum::Bool(a1.starts_with(a2.as_str())).to()
|
||||
} else {
|
||||
unreachable!()
|
||||
@ -1586,8 +1707,8 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::EndsWith => {
|
||||
if args.len() == 2 {
|
||||
if let VDataEnum::String(a1) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::String(a2) = args[1].run(vars, info).data {
|
||||
if let VDataEnum::String(a1) = &args[0].run(vars, info).data().0 {
|
||||
if let VDataEnum::String(a2) = &args[1].run(vars, info).data().0 {
|
||||
VDataEnum::Bool(a1.ends_with(a2.as_str())).to()
|
||||
} else {
|
||||
unreachable!()
|
||||
@ -1622,41 +1743,38 @@ impl BuiltinFunction {
|
||||
VDataEnum::Tuple(vec![]).to()
|
||||
}
|
||||
}
|
||||
match (find_in.data, pat.data) {
|
||||
(VDataEnum::String(a), VDataEnum::String(b)) => find(&a, &b),
|
||||
(VDataEnum::String(a), VDataEnum::Reference(b)) => {
|
||||
match &b.lock().unwrap().data {
|
||||
VDataEnum::String(b) => find(&a, b),
|
||||
let o = match (&find_in.data().0, &pat.data().0) {
|
||||
(VDataEnum::String(a), VDataEnum::String(b)) => find(a, b),
|
||||
(VDataEnum::String(a), VDataEnum::Reference(b)) => match &b.data().0 {
|
||||
VDataEnum::String(b) => find(a, b),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
(VDataEnum::Reference(a), VDataEnum::String(b)) => {
|
||||
match &a.lock().unwrap().data {
|
||||
VDataEnum::String(a) => find(a, &b),
|
||||
},
|
||||
(VDataEnum::Reference(a), VDataEnum::String(b)) => match &a.data().0 {
|
||||
VDataEnum::String(a) => find(a, b),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
},
|
||||
(VDataEnum::Reference(a), VDataEnum::Reference(b)) => {
|
||||
if Arc::ptr_eq(&a, &b) {
|
||||
if a.ptr_eq(b) {
|
||||
// point to the same string
|
||||
// (this is required because a.lock() would cause b.lock() to wait indefinitely if you pass a two references to the same string here)
|
||||
VDataEnum::Int(0).to()
|
||||
} else {
|
||||
match (&a.lock().unwrap().data, &b.lock().unwrap().data) {
|
||||
match (&a.data().0, &b.data().0) {
|
||||
(VDataEnum::String(a), VDataEnum::String(b)) => find(a, b),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
o
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
Self::Trim => {
|
||||
if args.len() == 1 {
|
||||
if let VDataEnum::String(a) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::String(a) = &args[0].run(vars, info).data().0 {
|
||||
VDataEnum::String(a.trim().to_string()).to()
|
||||
} else {
|
||||
unreachable!()
|
||||
@ -1667,18 +1785,18 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Substring => {
|
||||
if args.len() >= 2 {
|
||||
if let VDataEnum::String(a) = args[0].run(vars, info).data {
|
||||
if let VDataEnum::String(a) = &args[0].run(vars, info).data().0 {
|
||||
if args.len() > 3 {
|
||||
unreachable!()
|
||||
}
|
||||
let left = if let VDataEnum::Int(left) = args[1].run(vars, info).data {
|
||||
left
|
||||
let left = if let VDataEnum::Int(left) = &args[1].run(vars, info).data().0 {
|
||||
*left
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
let len = if args.len() == 3 {
|
||||
if let VDataEnum::Int(len) = args[2].run(vars, info).data {
|
||||
Some(len)
|
||||
if let VDataEnum::Int(len) = &args[2].run(vars, info).data().0 {
|
||||
Some(*len)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
@ -1714,20 +1832,21 @@ impl BuiltinFunction {
|
||||
}
|
||||
Self::Replace => {
|
||||
if let (VDataEnum::String(a), VDataEnum::String(b), VDataEnum::String(c)) = (
|
||||
args[0].run(vars, info).data,
|
||||
args[1].run(vars, info).data,
|
||||
args[2].run(vars, info).data,
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
&args[2].run(vars, info).data().0,
|
||||
) {
|
||||
VDataEnum::String(a.replace(&b, &c)).to()
|
||||
VDataEnum::String(a.replace(b, c)).to()
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
Self::Regex => {
|
||||
if args.len() == 2 {
|
||||
if let (VDataEnum::String(a), VDataEnum::String(regex)) =
|
||||
(args[0].run(vars, info).data, args[1].run(vars, info).data)
|
||||
{
|
||||
if let (VDataEnum::String(a), VDataEnum::String(regex)) = (
|
||||
&args[0].run(vars, info).data().0,
|
||||
&args[1].run(vars, info).data().0,
|
||||
) {
|
||||
match regex::Regex::new(regex.as_str()) {
|
||||
Ok(regex) => VDataEnum::List(
|
||||
VSingleType::String.to(),
|
||||
@ -1757,9 +1876,9 @@ impl BuiltinFunction {
|
||||
fn vdata_to_bytes(vd: &Vec<VData>) -> Option<Vec<u8>> {
|
||||
let mut bytes = Vec::with_capacity(vd.len());
|
||||
for b in vd {
|
||||
if let VDataEnum::Int(b) = b.data {
|
||||
bytes.push(if 0 <= b && b <= u8::MAX as isize {
|
||||
b as u8
|
||||
if let VDataEnum::Int(b) = &b.data().0 {
|
||||
bytes.push(if 0 <= *b && *b <= u8::MAX as isize {
|
||||
*b as u8
|
||||
} else if b.is_negative() {
|
||||
0
|
||||
} else {
|
||||
|
@ -8,17 +8,12 @@ use super::{
|
||||
val_type::{VSingleType, VType},
|
||||
};
|
||||
|
||||
type Am<T> = Arc<Mutex<T>>;
|
||||
fn am<T>(i: T) -> Am<T> {
|
||||
Arc::new(Mutex::new(i))
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RBlock {
|
||||
pub statements: Vec<RStatement>,
|
||||
}
|
||||
impl RBlock {
|
||||
pub fn run(&self, vars: &Vec<Am<VData>>, info: &GSInfo) -> VData {
|
||||
pub fn run(&self, vars: &mut Vec<VData>, info: &GSInfo) -> VData {
|
||||
let mut last = None;
|
||||
for statement in &self.statements {
|
||||
last = Some(statement.run(vars, info));
|
||||
@ -48,7 +43,7 @@ pub struct RFunction {
|
||||
pub block: RBlock,
|
||||
}
|
||||
impl RFunction {
|
||||
pub fn run(&self, vars: &Vec<Am<VData>>, info: &GSInfo) -> VData {
|
||||
pub fn run(&self, vars: &mut Vec<VData>, info: &GSInfo) -> VData {
|
||||
self.block.run(vars, info)
|
||||
}
|
||||
pub fn out(&self, input_types: &Vec<VSingleType>) -> VType {
|
||||
@ -91,19 +86,22 @@ pub struct RStatement {
|
||||
pub force_output_type: Option<VType>,
|
||||
}
|
||||
impl RStatement {
|
||||
pub fn run(&self, vars: &Vec<Am<VData>>, info: &GSInfo) -> VData {
|
||||
pub fn run(&self, vars: &mut Vec<VData>, info: &GSInfo) -> VData {
|
||||
let out = self.statement.run(vars, info);
|
||||
if let Some((v, derefs)) = self.output_to {
|
||||
let mut val = vars[v].clone();
|
||||
for _ in 0..derefs {
|
||||
let v = if let VDataEnum::Reference(v) = &val.lock().unwrap().data {
|
||||
v.clone()
|
||||
let mut val = dereference_n(&mut vars[v], derefs);
|
||||
fn dereference_n(d: &mut VData, n: usize) -> VData {
|
||||
if n > 0 {
|
||||
if let VDataEnum::Reference(v) = &mut d.data.lock().unwrap().0 {
|
||||
dereference_n(v, n - 1)
|
||||
} else {
|
||||
unreachable!("dereferencing something that isn't a reference in assignment")
|
||||
};
|
||||
val = v;
|
||||
}
|
||||
*val.lock().unwrap() = out;
|
||||
} else {
|
||||
d.clone_mut()
|
||||
}
|
||||
}
|
||||
val.assign(out.inner());
|
||||
VDataEnum::Tuple(vec![]).to()
|
||||
} else {
|
||||
out
|
||||
@ -142,7 +140,7 @@ pub enum RStatementEnum {
|
||||
EnumVariant(usize, RStatement),
|
||||
}
|
||||
impl RStatementEnum {
|
||||
pub fn run(&self, vars: &Vec<Am<VData>>, info: &GSInfo) -> VData {
|
||||
pub fn run(&self, vars: &mut Vec<VData>, info: &GSInfo) -> VData {
|
||||
match self {
|
||||
Self::Value(v) => v.clone(),
|
||||
Self::Tuple(v) => {
|
||||
@ -164,14 +162,16 @@ impl RStatementEnum {
|
||||
}
|
||||
Self::Variable(v, _, is_ref) => {
|
||||
if *is_ref {
|
||||
VDataEnum::Reference(vars[*v].clone()).to()
|
||||
// shared mutability (clone_mut)
|
||||
VDataEnum::Reference(vars[*v].clone_mut()).to()
|
||||
} else {
|
||||
vars[*v].lock().unwrap().clone()
|
||||
// Copy on Write (clone)
|
||||
vars[*v].clone()
|
||||
}
|
||||
}
|
||||
Self::FunctionCall(func, args) => {
|
||||
for (i, input) in func.inputs.iter().enumerate() {
|
||||
*vars[*input].lock().unwrap() = args[i].run(vars, info);
|
||||
vars[*input] = args[i].run(vars, info);
|
||||
}
|
||||
func.run(vars, info)
|
||||
}
|
||||
@ -180,8 +180,8 @@ impl RStatementEnum {
|
||||
.run_fn(*fnid, args.iter().map(|arg| arg.run(vars, info)).collect()),
|
||||
Self::Block(b) => b.run(vars, info),
|
||||
Self::If(c, t, e) => {
|
||||
if let VDataEnum::Bool(v) = c.run(vars, info).data {
|
||||
if v {
|
||||
if let VDataEnum::Bool(v) = &c.run(vars, info).data().0 {
|
||||
if *v {
|
||||
t.run(vars, info)
|
||||
} else {
|
||||
if let Some(e) = e {
|
||||
@ -196,7 +196,7 @@ impl RStatementEnum {
|
||||
}
|
||||
Self::Loop(c) => loop {
|
||||
// loops will break if the value matches.
|
||||
if let Some(break_val) = c.run(vars, info).data.matches() {
|
||||
if let Some(break_val) = c.run(vars, info).inner().matches() {
|
||||
break break_val;
|
||||
}
|
||||
},
|
||||
@ -204,17 +204,17 @@ impl RStatementEnum {
|
||||
// matching values also break with value from a for loop.
|
||||
let c = c.run(vars, info);
|
||||
let mut vars = vars.clone();
|
||||
let in_loop = |vars: &mut Vec<Arc<Mutex<VData>>>, c| {
|
||||
vars[*v] = Arc::new(Mutex::new(c));
|
||||
b.run(&vars, info)
|
||||
let in_loop = |vars: &mut Vec<VData>, c| {
|
||||
vars[*v] = c;
|
||||
b.run(vars, info)
|
||||
};
|
||||
|
||||
let mut oval = VDataEnum::Tuple(vec![]).to();
|
||||
match c.data {
|
||||
match &c.data().0 {
|
||||
VDataEnum::Int(v) => {
|
||||
for i in 0..v {
|
||||
for i in 0..*v {
|
||||
if let Some(v) =
|
||||
in_loop(&mut vars, VDataEnum::Int(i).to()).data.matches()
|
||||
in_loop(&mut vars, VDataEnum::Int(i).to()).inner().matches()
|
||||
{
|
||||
oval = v;
|
||||
break;
|
||||
@ -225,7 +225,7 @@ impl RStatementEnum {
|
||||
for ch in v.chars() {
|
||||
if let Some(v) =
|
||||
in_loop(&mut vars, VDataEnum::String(ch.to_string()).to())
|
||||
.data
|
||||
.inner()
|
||||
.matches()
|
||||
{
|
||||
oval = v;
|
||||
@ -235,15 +235,15 @@ impl RStatementEnum {
|
||||
}
|
||||
VDataEnum::Tuple(v) | VDataEnum::List(_, v) => {
|
||||
for v in v {
|
||||
if let Some(v) = in_loop(&mut vars, v).data.matches() {
|
||||
if let Some(v) = in_loop(&mut vars, v.clone()).inner().matches() {
|
||||
oval = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
VDataEnum::Function(f) => loop {
|
||||
if let Some(v) = f.run(&vars, info).data.matches() {
|
||||
if let Some(v) = in_loop(&mut vars, v).data.matches() {
|
||||
if let Some(v) = f.run(&mut vars, info).inner().matches() {
|
||||
if let Some(v) = in_loop(&mut vars, v).inner().matches() {
|
||||
oval = v;
|
||||
break;
|
||||
}
|
||||
@ -270,10 +270,10 @@ impl RStatementEnum {
|
||||
Self::Match(match_on, cases) => 'm: {
|
||||
for (case_condition, case_action) in cases {
|
||||
// [t] => Some(t), t => Some(t), [] | false => None
|
||||
if let Some(v) = case_condition.run(vars, info).data.matches() {
|
||||
let og = { std::mem::replace(&mut *vars[*match_on].lock().unwrap(), v) };
|
||||
if let Some(v) = case_condition.run(vars, info).inner().matches() {
|
||||
let og = { std::mem::replace(&mut vars[*match_on], v) };
|
||||
let res = case_action.run(vars, info);
|
||||
*vars[*match_on].lock().unwrap() = og;
|
||||
vars[*match_on] = og;
|
||||
break 'm res;
|
||||
}
|
||||
}
|
||||
@ -377,17 +377,19 @@ impl RScript {
|
||||
}
|
||||
pub fn run(&self, args: Vec<String>) -> VData {
|
||||
let mut vars = Vec::with_capacity(self.info.vars);
|
||||
vars.push(am(VDataEnum::List(
|
||||
vars.push(
|
||||
VDataEnum::List(
|
||||
VSingleType::String.into(),
|
||||
args.into_iter()
|
||||
.map(|v| VDataEnum::String(v).to())
|
||||
.collect(),
|
||||
)
|
||||
.to()));
|
||||
.to(),
|
||||
);
|
||||
for _i in 1..self.info.vars {
|
||||
vars.push(am(VDataEnum::Tuple(vec![]).to()));
|
||||
vars.push(VDataEnum::Tuple(vec![]).to());
|
||||
}
|
||||
self.main.run(&vars, &self.info)
|
||||
self.main.run(&mut vars, &self.info)
|
||||
}
|
||||
pub fn info(&self) -> &GSInfo {
|
||||
&self.info
|
||||
|
@ -5,16 +5,101 @@ use std::{
|
||||
|
||||
use super::{
|
||||
code_runnable::RFunction,
|
||||
global_info::{GlobalScriptInfo, GSInfo},
|
||||
global_info::{GSInfo, GlobalScriptInfo},
|
||||
val_type::{VSingleType, VType},
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct VData {
|
||||
pub data: VDataEnum,
|
||||
/// (_, mutable) - if false, behave as CopyOnWrite.
|
||||
pub data: Arc<Mutex<(VDataEnum, bool)>>,
|
||||
}
|
||||
impl VData {
|
||||
/// if self is mutable, assigns the new value to the mutex.
|
||||
/// if self is immutable, creates a new mutex and sets self to mutable.
|
||||
pub fn assign(&mut self, new_val: VDataEnum) {
|
||||
{
|
||||
let mut d = self.data.lock().unwrap();
|
||||
if d.1 {
|
||||
d.0 = new_val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
*self = new_val.to();
|
||||
}
|
||||
pub fn inner_replace(&mut self, new_val: VDataEnum) -> VDataEnum {
|
||||
{
|
||||
let mut d = self.data.lock().unwrap();
|
||||
if d.1 {
|
||||
return std::mem::replace(&mut d.0, new_val);
|
||||
}
|
||||
}
|
||||
let o = self.data().0.clone();
|
||||
*self = new_val.to();
|
||||
o
|
||||
}
|
||||
/// returns the contained VDataEnum. May or may not clone.
|
||||
pub fn inner(self) -> VDataEnum {
|
||||
self.data().0.clone()
|
||||
}
|
||||
/// ensures self is mutable, then returns a new instance of VData that is also mutable and uses the same Arc<Mutex<_>>.
|
||||
pub fn clone_mut(&mut self) -> Self {
|
||||
// if not mutable, copy and set to mutable.
|
||||
self.make_mut();
|
||||
// now, both self and the returned value are set to mutable and share the same mutex.
|
||||
self.clone_mut_assume()
|
||||
}
|
||||
/// like clone_mut, but assumes self is already mutable, and therefor does not need to mutate self
|
||||
/// as the Arc<Mutex<_>> will stay the same.
|
||||
pub fn clone_mut_assume(&self) -> Self {
|
||||
Self {
|
||||
data: Arc::clone(&self.data),
|
||||
}
|
||||
}
|
||||
pub fn ptr_eq(&self, rhs: &Self) -> bool {
|
||||
Arc::ptr_eq(&self.data, &rhs.data)
|
||||
}
|
||||
/// makes self mutable. might clone.
|
||||
pub fn make_mut(&mut self) -> &mut Self {
|
||||
{
|
||||
let mut s = self.data.lock().unwrap();
|
||||
if !s.1 {
|
||||
*s = (s.0.clone(), true);
|
||||
}
|
||||
}
|
||||
self
|
||||
}
|
||||
pub fn data(&self) -> std::sync::MutexGuard<(VDataEnum, bool)> {
|
||||
self.data.lock().unwrap()
|
||||
}
|
||||
}
|
||||
impl Clone for VData {
|
||||
fn clone(&self) -> Self {
|
||||
let mut d = self.data.lock().unwrap();
|
||||
// set to immutable, locking the data as-is.
|
||||
d.1 = false;
|
||||
// then return the same arc (-> avoid cloning)
|
||||
Self {
|
||||
data: Arc::clone(&self.data),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Debug for VData {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
let d = self.data.lock().unwrap();
|
||||
if d.1 {
|
||||
write!(f, "(!mutable!):{:?}", d.0)
|
||||
} else {
|
||||
write!(f, "(immutable):{:?}", d.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
impl PartialEq for VData {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.data().0 == other.data().0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub enum VDataEnum {
|
||||
Bool(bool),
|
||||
Int(isize),
|
||||
@ -24,15 +109,34 @@ pub enum VDataEnum {
|
||||
List(VType, Vec<VData>),
|
||||
Function(RFunction),
|
||||
Thread(thread::VDataThread, VType),
|
||||
Reference(Arc<Mutex<VData>>),
|
||||
Reference(VData),
|
||||
EnumVariant(usize, Box<VData>),
|
||||
}
|
||||
impl Clone for VDataEnum {
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
// exception: don't clone the value AND don't use CoW,
|
||||
// because we want to share the same Arc<Mutex<_>>.
|
||||
Self::Reference(r) => Self::Reference(r.clone_mut_assume()),
|
||||
// default impls
|
||||
Self::Bool(b) => Self::Bool(*b),
|
||||
Self::Int(i) => Self::Int(*i),
|
||||
Self::Float(f) => Self::Float(*f),
|
||||
Self::String(s) => Self::String(s.clone()),
|
||||
Self::Tuple(v) => Self::Tuple(v.clone()),
|
||||
Self::List(t, v) => Self::List(t.clone(), v.clone()),
|
||||
Self::Function(f) => Self::Function(f.clone()),
|
||||
Self::Thread(th, ty) => Self::Thread(th.clone(), ty.clone()),
|
||||
Self::EnumVariant(v, d) => Self::EnumVariant(v.clone(), d.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl PartialEq for VDataEnum {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Self::Reference(a), Self::Reference(b)) => *a.lock().unwrap() == *b.lock().unwrap(),
|
||||
(Self::Reference(a), b) => a.lock().unwrap().data == *b,
|
||||
(a, Self::Reference(b)) => *a == b.lock().unwrap().data,
|
||||
(Self::Reference(a), Self::Reference(b)) => a == b,
|
||||
(Self::Reference(a), b) => &a.data().0 == b,
|
||||
(a, Self::Reference(b)) => a == &b.data().0,
|
||||
(Self::Bool(a), Self::Bool(b)) => *a == *b,
|
||||
(Self::Int(a), Self::Int(b)) => *a == *b,
|
||||
(Self::Float(a), Self::Float(b)) => *a == *b,
|
||||
@ -48,7 +152,7 @@ impl PartialEq for VDataEnum {
|
||||
|
||||
impl VData {
|
||||
pub fn safe_to_share(&self) -> bool {
|
||||
self.data.safe_to_share()
|
||||
self.data().0.safe_to_share()
|
||||
}
|
||||
pub fn out(&self) -> VType {
|
||||
VType {
|
||||
@ -56,7 +160,7 @@ impl VData {
|
||||
}
|
||||
}
|
||||
pub fn out_single(&self) -> VSingleType {
|
||||
match &self.data {
|
||||
match &self.data().0 {
|
||||
VDataEnum::Bool(..) => VSingleType::Bool,
|
||||
VDataEnum::Int(..) => VSingleType::Int,
|
||||
VDataEnum::Float(..) => VSingleType::Float,
|
||||
@ -65,21 +169,23 @@ impl VData {
|
||||
VDataEnum::List(t, _) => VSingleType::List(t.clone()),
|
||||
VDataEnum::Function(f) => VSingleType::Function(f.input_output_map.clone()),
|
||||
VDataEnum::Thread(_, o) => VSingleType::Thread(o.clone()),
|
||||
VDataEnum::Reference(r) => r.lock().unwrap().out_single(),
|
||||
VDataEnum::Reference(r) => VSingleType::Reference(Box::new(r.out_single())),
|
||||
VDataEnum::EnumVariant(e, v) => VSingleType::EnumVariant(*e, v.out()),
|
||||
}
|
||||
}
|
||||
pub fn get(&self, i: usize) -> Option<Self> {
|
||||
self.data.get(i)
|
||||
self.data().0.get(i)
|
||||
}
|
||||
pub fn noenum(self) -> Self {
|
||||
self.data.noenum()
|
||||
self.inner().noenum()
|
||||
}
|
||||
}
|
||||
|
||||
impl VDataEnum {
|
||||
pub fn to(self) -> VData {
|
||||
VData { data: self }
|
||||
VData {
|
||||
data: Arc::new(Mutex::new((self, true))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,7 +219,7 @@ impl VDataEnum {
|
||||
None => None,
|
||||
},
|
||||
Self::Tuple(v) | Self::List(_, v) => v.get(i).cloned(),
|
||||
Self::Reference(r) => r.lock().unwrap().get(i),
|
||||
Self::Reference(r) => r.get(i),
|
||||
Self::EnumVariant(_, v) => v.get(i),
|
||||
}
|
||||
}
|
||||
@ -286,13 +392,17 @@ impl VDataEnum {
|
||||
Self::Thread(..) => write!(f, "[TODO] THREAD"),
|
||||
Self::Reference(inner) => {
|
||||
write!(f, "&")?;
|
||||
inner.lock().unwrap().fmtgs(f, info)
|
||||
inner.fmtgs(f, info)
|
||||
}
|
||||
Self::EnumVariant(variant, inner) => {
|
||||
if let Some(name) = if let Some(info) = info {
|
||||
info.enum_variants
|
||||
.iter()
|
||||
.find_map(|(name, id)| if id == variant { Some(name) } else { None })
|
||||
info.enum_variants.iter().find_map(|(name, id)| {
|
||||
if id == variant {
|
||||
Some(name)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
} else {
|
||||
None
|
||||
} {
|
||||
@ -313,7 +423,7 @@ impl Display for VDataEnum {
|
||||
|
||||
impl VData {
|
||||
pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result {
|
||||
self.data.fmtgs(f, info)
|
||||
self.data().0.fmtgs(f, info)
|
||||
}
|
||||
}
|
||||
impl Display for VData {
|
||||
|
@ -14,7 +14,7 @@ pub fn run(tutor: &mut Tutor) {
|
||||
",
|
||||
));
|
||||
loop {
|
||||
match tutor.let_user_make_change().run(vec![]).data {
|
||||
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||
VDataEnum::Bool(true) => break,
|
||||
other => {
|
||||
tutor.set_status(format!(" - Returned {} instead of true.", other));
|
||||
|
@ -35,7 +35,7 @@ mul()
|
||||
",
|
||||
));
|
||||
loop {
|
||||
match tutor.let_user_make_change().run(vec![]).data {
|
||||
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||
VDataEnum::Int(160) => break,
|
||||
other => {
|
||||
tutor.set_status(format!(" - Returned {other} instead of 160"));
|
||||
|
@ -27,7 +27,7 @@ fn compute_sum(a int b int) {
|
||||
",
|
||||
));
|
||||
loop {
|
||||
match tutor.let_user_make_change().run(vec![]).data {
|
||||
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||
VDataEnum::Int(15) => break,
|
||||
other => {
|
||||
tutor.set_status(format!(" - Returned {} instead of 15.", other));
|
||||
|
@ -54,7 +54,7 @@ switch! words_in_string {}
|
||||
true
|
||||
"));
|
||||
loop {
|
||||
match tutor.let_user_make_change().run(vec![]).data {
|
||||
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||
VDataEnum::Tuple(v) if v.is_empty() => {
|
||||
tutor.set_status(format!(" - Returned an empty tuple."));
|
||||
tutor.update(None);
|
||||
|
@ -24,7 +24,7 @@ pub fn run(tutor: &mut Tutor) {
|
||||
// return any enum to return to the menu.
|
||||
"));
|
||||
loop {
|
||||
match tutor.let_user_make_change().run(vec![]).data {
|
||||
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||
VDataEnum::EnumVariant(..) => break,
|
||||
other => {
|
||||
tutor.set_status(format!(" - Returned {other} instead of an enum."));
|
||||
|
@ -18,9 +18,9 @@ five_less = sub(my_first_variable 5) // 10
|
||||
",
|
||||
));
|
||||
loop {
|
||||
match tutor.let_user_make_change().run(vec![]).data {
|
||||
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||
VDataEnum::String(name) if !name.is_empty() => {
|
||||
tutor.i_name = Some(name);
|
||||
tutor.i_name = Some(name.to_owned());
|
||||
break;
|
||||
}
|
||||
VDataEnum::String(_) => {
|
||||
|
@ -44,7 +44,7 @@ switch! first {
|
||||
list.get(8)
|
||||
"));
|
||||
loop {
|
||||
match tutor.let_user_make_change().run(vec![]).data {
|
||||
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||
VDataEnum::Tuple(v) if !v.is_empty() => {
|
||||
break;
|
||||
}
|
||||
|
@ -24,9 +24,9 @@ go_to()
|
||||
",
|
||||
));
|
||||
loop {
|
||||
match tutor.let_user_make_change().run(vec![]).data {
|
||||
VDataEnum::Int(pos) if pos != 0 => {
|
||||
tutor.current_pos = (pos.max(0) as usize).min(MAX_POS);
|
||||
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||
VDataEnum::Int(pos) if *pos != 0 => {
|
||||
tutor.current_pos = ((*pos).max(0) as usize).min(MAX_POS);
|
||||
match tutor.current_pos {
|
||||
0 => continue,
|
||||
1 => super::base_comments::run(&mut tutor),
|
||||
|
@ -45,7 +45,7 @@ false
|
||||
i_name: None,
|
||||
};
|
||||
loop {
|
||||
if let VDataEnum::Bool(true) = tutor.let_user_make_change().run(vec![]).data {
|
||||
if let VDataEnum::Bool(true) = &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ fn run_all() {
|
||||
let mut file = File::new(fs::read_to_string(file.path()).unwrap(), file.path());
|
||||
// has to return true, otherwise the test will fail
|
||||
assert!(matches!(
|
||||
parse::parse(&mut file).unwrap().run(vec![]).data,
|
||||
parse::parse(&mut file).unwrap().run(vec![]).data().0,
|
||||
VDataEnum::Bool(true)
|
||||
));
|
||||
}
|
||||
|
@ -57,8 +57,11 @@ fn main() {
|
||||
.unwrap()
|
||||
.1;
|
||||
my_lib.callbacks.run_function.consuming = Some(Box::new(move |msg| {
|
||||
if let VDataEnum::String(url) = &msg.msg.args[0].data {
|
||||
let url = url.clone();
|
||||
let url = if let VDataEnum::String(url) = &msg.msg.args[0].data().0 {
|
||||
url.clone()
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
std::thread::spawn(move || {
|
||||
let r = match reqwest::blocking::get(url) {
|
||||
Ok(response) => match response.text() {
|
||||
@ -89,9 +92,6 @@ fn main() {
|
||||
};
|
||||
msg.respond(r)
|
||||
});
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}));
|
||||
// because we handle all callbacks, this never returns Err(unhandeled message).
|
||||
// it returns Ok(()) if mers exits (i/o error in stdin/stdout), so we also exit if that happens.
|
||||
|
Loading…
Reference in New Issue
Block a user