mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
changed while loop break to use matching (any matching value breaks) and added the same break functionality to for loops.
This commit is contained in:
parent
52973eb0f8
commit
260e42d4a7
@ -728,45 +728,49 @@ impl RStatementEnum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::While(c) => loop {
|
Self::While(c) => loop {
|
||||||
// While loops blocks can return a bool (false to break from the loop) or a 0-1 length tuple (0-length => continue, 1-length => break with value)
|
// While loops will break if the value matches.
|
||||||
match c.run(vars, libs).data {
|
if let Some(break_val) = c.run(vars, libs).data.matches() {
|
||||||
VDataEnum::Bool(v) => {
|
break break_val;
|
||||||
if !v {
|
|
||||||
break VDataEnum::Tuple(vec![]).to();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VDataEnum::Tuple(v) if v.len() == 0 => (),
|
|
||||||
VDataEnum::Tuple(v) if v.len() == 1 => break v[0].clone(),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Self::For(v, c, b) => {
|
Self::For(v, c, b) => {
|
||||||
|
// matching values also break with value from a for loop.
|
||||||
let c = c.run(vars, libs);
|
let c = c.run(vars, libs);
|
||||||
let mut vars = vars.clone();
|
let mut vars = vars.clone();
|
||||||
let mut in_loop = |c| {
|
let mut in_loop = |c| {
|
||||||
vars[*v] = Arc::new(Mutex::new(c));
|
vars[*v] = Arc::new(Mutex::new(c));
|
||||||
b.run(&vars, libs);
|
b.run(&vars, libs)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut oval = VDataEnum::Tuple(vec![]).to();
|
||||||
match c.data {
|
match c.data {
|
||||||
VDataEnum::Int(v) => {
|
VDataEnum::Int(v) => {
|
||||||
for i in 0..v {
|
for i in 0..v {
|
||||||
in_loop(VDataEnum::Int(i).to());
|
if let Some(v) = in_loop(VDataEnum::Int(i).to()).data.matches() {
|
||||||
|
oval = v;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VDataEnum::String(v) => {
|
VDataEnum::String(v) => {
|
||||||
for ch in v.chars() {
|
for ch in v.chars() {
|
||||||
in_loop(VDataEnum::String(ch.to_string()).to())
|
if let Some(v) = in_loop(VDataEnum::String(ch.to_string()).to()).data.matches() {
|
||||||
|
oval = v;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VDataEnum::Tuple(v) | VDataEnum::List(_, v) => {
|
VDataEnum::Tuple(v) | VDataEnum::List(_, v) => {
|
||||||
for v in v {
|
for v in v {
|
||||||
in_loop(v)
|
if let Some(v) = in_loop(v).data.matches() {
|
||||||
|
oval = v;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
VDataEnum::Tuple(vec![]).to()
|
oval
|
||||||
}
|
}
|
||||||
Self::Switch(switch_on, cases) => {
|
Self::Switch(switch_on, cases) => {
|
||||||
let switch_on = switch_on.run(vars, libs);
|
let switch_on = switch_on.run(vars, libs);
|
||||||
@ -782,12 +786,8 @@ impl RStatementEnum {
|
|||||||
}
|
}
|
||||||
Self::Match(match_on, cases) => 'm: {
|
Self::Match(match_on, cases) => 'm: {
|
||||||
for (case_condition, case_action) in cases {
|
for (case_condition, case_action) in cases {
|
||||||
// [t] => Some(t), t => Some(t), [] => None
|
// [t] => Some(t), t => Some(t), [] | false => None
|
||||||
if let Some(v) = match case_condition.run(vars, libs).data {
|
if let Some(v) = case_condition.run(vars, libs).data.matches() {
|
||||||
VDataEnum::Tuple(mut tuple) => tuple.pop(),
|
|
||||||
VDataEnum::Bool(v) => if v { Some(VDataEnum::Bool(v).to()) } else { None },
|
|
||||||
other => Some(other.to()),
|
|
||||||
} {
|
|
||||||
let og = {
|
let og = {
|
||||||
std::mem::replace(&mut *vars[*match_on].lock().unwrap(), v)
|
std::mem::replace(&mut *vars[*match_on].lock().unwrap(), v)
|
||||||
};
|
};
|
||||||
@ -837,33 +837,10 @@ impl RStatementEnum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::While(c) => {
|
Self::While(c) => {
|
||||||
let mut output_types = VType { types: vec![] };
|
c.out().matches().1
|
||||||
for t in c.out().types {
|
|
||||||
match t {
|
|
||||||
VSingleType::Bool => {
|
|
||||||
output_types = output_types | VSingleType::Tuple(vec![]).to();
|
|
||||||
}
|
|
||||||
VSingleType::Tuple(mut t) => {
|
|
||||||
if !t.is_empty() {
|
|
||||||
if t.len() != 1 {
|
|
||||||
unreachable!("while loop with tuple of length {}>1.", t.len());
|
|
||||||
}
|
|
||||||
output_types = output_types | t.pop().unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!(
|
|
||||||
"while loop statement didn't return bool or 0-1 length tuple."
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output_types
|
|
||||||
}
|
}
|
||||||
Self::For(_, _, b) => {
|
Self::For(_, _, b) => {
|
||||||
// returns the return value from the last iteration or nothing if there was no iteration
|
VSingleType::Tuple(vec![]).to() | b.out().matches().1
|
||||||
b.out()
|
|
||||||
| VType {
|
|
||||||
types: vec![VSingleType::Tuple(vec![])],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Self::BuiltinFunction(f, args) => f.returns(args.iter().map(|rs| rs.out()).collect()),
|
Self::BuiltinFunction(f, args) => f.returns(args.iter().map(|rs| rs.out()).collect()),
|
||||||
Self::Switch(switch_on, cases) => {
|
Self::Switch(switch_on, cases) => {
|
||||||
|
@ -77,7 +77,54 @@ impl VDataEnum {
|
|||||||
Self::Reference(r) => r.lock().unwrap().get(i),
|
Self::Reference(r) => r.lock().unwrap().get(i),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn matches_ref_bool(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
VDataEnum::Tuple(v) => !v.is_empty(),
|
||||||
|
VDataEnum::Bool(false) => false,
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn matches(self) -> Option<VData> {
|
||||||
|
match self {
|
||||||
|
VDataEnum::Tuple(mut tuple) => tuple.pop(),
|
||||||
|
VDataEnum::Bool(v) => {
|
||||||
|
if v {
|
||||||
|
Some(VDataEnum::Bool(v).to())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
other => Some(other.to()),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
impl VSingleType {
|
||||||
|
/// returns (can_fail_to_match, matches_as)
|
||||||
|
pub fn matches(&self) -> (bool, VType) {
|
||||||
|
match self {
|
||||||
|
Self::Tuple(v) => match v.first() {
|
||||||
|
Some(v) => (false, v.clone()),
|
||||||
|
None => (true, VType { types: vec![] }),
|
||||||
|
},
|
||||||
|
Self::Bool => (true, Self::Bool.to()),
|
||||||
|
v => (false, v.clone().to()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl VType {
|
||||||
|
/// returns (can_fail_to_match, matches_as)
|
||||||
|
pub fn matches(&self) -> (bool, VType) {
|
||||||
|
let mut can_fail = false;
|
||||||
|
let mut matches_as = VType { types: vec![] };
|
||||||
|
for t in self.types.iter() {
|
||||||
|
let (f, t) = t.matches();
|
||||||
|
can_fail |= f;
|
||||||
|
matches_as = matches_as | t;
|
||||||
|
}
|
||||||
|
(can_fail, matches_as)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct VDataThread(Arc<Mutex<VDataThreadEnum>>);
|
pub struct VDataThread(Arc<Mutex<VDataThreadEnum>>);
|
||||||
impl VDataThread {
|
impl VDataThread {
|
||||||
|
Loading…
Reference in New Issue
Block a user