mirror of
https://github.com/tweag/nickel.git
synced 2024-10-06 08:07:37 +03:00
Merge pull request #443 from tweag/timcer/op_refactor
Refactoring operation continuation with Strictness markers on stack
This commit is contained in:
commit
9856905253
32
src/eval.rs
32
src/eval.rs
@ -527,18 +527,19 @@ where
|
||||
}
|
||||
}
|
||||
Term::Op1(op, t) => {
|
||||
let prev_strict = enriched_strict;
|
||||
if !enriched_strict {
|
||||
stack.push_strictness(enriched_strict);
|
||||
}
|
||||
enriched_strict = true;
|
||||
stack.push_op_cont(
|
||||
OperationCont::Op1(op, t.pos, prev_strict),
|
||||
call_stack.len(),
|
||||
pos,
|
||||
);
|
||||
stack.push_op_cont(OperationCont::Op1(op, t.pos), call_stack.len(), pos);
|
||||
Closure { body: t, env }
|
||||
}
|
||||
Term::Op2(op, fst, snd) => {
|
||||
let prev_strict = enriched_strict;
|
||||
enriched_strict = op.is_strict();
|
||||
let strict_op = op.is_strict();
|
||||
if enriched_strict != strict_op {
|
||||
stack.push_strictness(enriched_strict);
|
||||
}
|
||||
enriched_strict = strict_op;
|
||||
stack.push_op_cont(
|
||||
OperationCont::Op2First(
|
||||
op,
|
||||
@ -547,7 +548,6 @@ where
|
||||
env: env.clone(),
|
||||
},
|
||||
fst.pos,
|
||||
prev_strict,
|
||||
),
|
||||
call_stack.len(),
|
||||
pos,
|
||||
@ -555,8 +555,11 @@ where
|
||||
Closure { body: fst, env }
|
||||
}
|
||||
Term::OpN(op, mut args) => {
|
||||
let prev_strict = enriched_strict;
|
||||
enriched_strict = op.is_strict();
|
||||
let strict_op = op.is_strict();
|
||||
if enriched_strict != strict_op {
|
||||
stack.push_strictness(enriched_strict);
|
||||
}
|
||||
enriched_strict = strict_op;
|
||||
|
||||
// Arguments are passed as a stack to the operation continuation, so we reverse the
|
||||
// original list.
|
||||
@ -579,7 +582,6 @@ where
|
||||
evaluated: Vec::with_capacity(pending.len() + 1),
|
||||
pending,
|
||||
current_pos: fst.pos,
|
||||
prev_enriched_strict: prev_strict,
|
||||
},
|
||||
call_stack.len(),
|
||||
pos,
|
||||
@ -598,6 +600,10 @@ where
|
||||
StrChunk::Expr(e, indent) => (e, indent),
|
||||
};
|
||||
|
||||
if !enriched_strict {
|
||||
stack.push_strictness(enriched_strict);
|
||||
}
|
||||
enriched_strict = true;
|
||||
stack.push_str_chunks(chunks.into_iter());
|
||||
stack.push_str_acc(String::new(), indent, env.clone());
|
||||
|
||||
@ -788,7 +794,7 @@ where
|
||||
update_thunks(&mut stack, &clos);
|
||||
clos
|
||||
} else {
|
||||
continuate_operation(clos, &mut stack, &mut call_stack, &mut enriched_strict)?
|
||||
continuate_operation(clos, &mut stack, &mut call_stack)?
|
||||
}
|
||||
}
|
||||
// Function call
|
||||
|
@ -47,21 +47,18 @@ pub enum OperationCont {
|
||||
Op1(
|
||||
/* unary operation */ UnaryOp,
|
||||
/* original position of the argument before evaluation */ TermPos,
|
||||
/* previous value of enriched_strict */ bool,
|
||||
),
|
||||
// The last parameter saves the strictness mode before the evaluation of the operator
|
||||
Op2First(
|
||||
/* the binary operation */ BinaryOp,
|
||||
/* second argument, to evaluate next */ Closure,
|
||||
/* original position of the first argument */ TermPos,
|
||||
/* previous value of enriched_strict */ bool,
|
||||
),
|
||||
Op2Second(
|
||||
/* binary operation */ BinaryOp,
|
||||
/* first argument, evaluated */ Closure,
|
||||
/* original position of the first argument before evaluation */ TermPos,
|
||||
/* original position of the second argument before evaluation */ TermPos,
|
||||
/* previous value of enriched_strict */ bool,
|
||||
),
|
||||
OpN {
|
||||
op: NAryOp, /* the n-ary operation */
|
||||
@ -69,16 +66,15 @@ pub enum OperationCont {
|
||||
current_pos: TermPos, /* original position of the argument being currently evaluated */
|
||||
pending: Vec<Closure>, /* a stack (meaning the order of arguments is to be reversed)
|
||||
of arguments yet to be evaluated */
|
||||
prev_enriched_strict: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for OperationCont {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
OperationCont::Op1(op, _, _) => write!(f, "Op1 {:?}", op),
|
||||
OperationCont::Op2First(op, _, _, _) => write!(f, "Op2First {:?}", op),
|
||||
OperationCont::Op2Second(op, _, _, _, _) => write!(f, "Op2Second {:?}", op),
|
||||
OperationCont::Op1(op, _) => write!(f, "Op1 {:?}", op),
|
||||
OperationCont::Op2First(op, _, _) => write!(f, "Op2First {:?}", op),
|
||||
OperationCont::Op2Second(op, _, _, _) => write!(f, "Op2Second {:?}", op),
|
||||
OperationCont::OpN { op, .. } => write!(f, "OpN {:?}", op),
|
||||
}
|
||||
}
|
||||
@ -93,29 +89,26 @@ pub fn continuate_operation(
|
||||
mut clos: Closure,
|
||||
stack: &mut Stack,
|
||||
call_stack: &mut CallStack,
|
||||
enriched_strict: &mut bool,
|
||||
) -> Result<Closure, EvalError> {
|
||||
let (cont, cs_len, pos) = stack.pop_op_cont().expect("Condition already checked");
|
||||
call_stack.truncate(cs_len);
|
||||
match cont {
|
||||
OperationCont::Op1(u_op, arg_pos, prev_strict) => {
|
||||
OperationCont::Op1(u_op, arg_pos) => {
|
||||
let result = process_unary_operation(u_op, clos, arg_pos, stack, call_stack, pos);
|
||||
*enriched_strict = prev_strict;
|
||||
result
|
||||
}
|
||||
OperationCont::Op2First(b_op, mut snd_clos, fst_pos, prev_strict) => {
|
||||
OperationCont::Op2First(b_op, mut snd_clos, fst_pos) => {
|
||||
std::mem::swap(&mut clos, &mut snd_clos);
|
||||
stack.push_op_cont(
|
||||
OperationCont::Op2Second(b_op, snd_clos, fst_pos, clos.body.pos, prev_strict),
|
||||
OperationCont::Op2Second(b_op, snd_clos, fst_pos, clos.body.pos),
|
||||
cs_len,
|
||||
pos,
|
||||
);
|
||||
Ok(clos)
|
||||
}
|
||||
OperationCont::Op2Second(b_op, fst_clos, fst_pos, snd_pos, prev_strict) => {
|
||||
OperationCont::Op2Second(b_op, fst_clos, fst_pos, snd_pos) => {
|
||||
let result =
|
||||
process_binary_operation(b_op, fst_clos, fst_pos, clos, snd_pos, stack, pos);
|
||||
*enriched_strict = prev_strict;
|
||||
result
|
||||
}
|
||||
OperationCont::OpN {
|
||||
@ -123,7 +116,6 @@ pub fn continuate_operation(
|
||||
mut evaluated,
|
||||
current_pos,
|
||||
mut pending,
|
||||
prev_enriched_strict,
|
||||
} => {
|
||||
evaluated.push((clos, current_pos));
|
||||
|
||||
@ -135,7 +127,6 @@ pub fn continuate_operation(
|
||||
evaluated,
|
||||
current_pos,
|
||||
pending,
|
||||
prev_enriched_strict,
|
||||
},
|
||||
cs_len,
|
||||
pos,
|
||||
@ -144,7 +135,6 @@ pub fn continuate_operation(
|
||||
Ok(next)
|
||||
} else {
|
||||
let result = process_nary_operation(op, evaluated, stack, pos);
|
||||
*enriched_strict = prev_enriched_strict;
|
||||
result
|
||||
}
|
||||
}
|
||||
@ -2314,7 +2304,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn ite_operation() {
|
||||
let cont = OperationCont::Op1(UnaryOp::Ite(), TermPos::None, true);
|
||||
let cont = OperationCont::Op1(UnaryOp::Ite(), TermPos::None);
|
||||
let mut stack = Stack::new();
|
||||
stack.push_arg(
|
||||
Closure::atomic_closure(Term::Num(5.0).into()),
|
||||
@ -2332,9 +2322,8 @@ mod tests {
|
||||
|
||||
stack.push_op_cont(cont, 0, TermPos::None);
|
||||
let mut call_stack = CallStack::new();
|
||||
let mut strict = true;
|
||||
|
||||
clos = continuate_operation(clos, &mut stack, &mut call_stack, &mut strict).unwrap();
|
||||
clos = continuate_operation(clos, &mut stack, &mut call_stack).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
clos,
|
||||
@ -2355,7 +2344,6 @@ mod tests {
|
||||
env: Environment::new(),
|
||||
},
|
||||
TermPos::None,
|
||||
true,
|
||||
);
|
||||
|
||||
let mut clos = Closure {
|
||||
@ -2365,9 +2353,8 @@ mod tests {
|
||||
let mut stack = Stack::new();
|
||||
stack.push_op_cont(cont, 0, TermPos::None);
|
||||
let mut call_stack = CallStack::new();
|
||||
let mut strict = true;
|
||||
|
||||
clos = continuate_operation(clos, &mut stack, &mut call_stack, &mut strict).unwrap();
|
||||
clos = continuate_operation(clos, &mut stack, &mut call_stack).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
clos,
|
||||
@ -2388,7 +2375,6 @@ mod tests {
|
||||
},
|
||||
TermPos::None,
|
||||
TermPos::None,
|
||||
true
|
||||
),
|
||||
0,
|
||||
TermPos::None
|
||||
@ -2407,7 +2393,6 @@ mod tests {
|
||||
},
|
||||
TermPos::None,
|
||||
TermPos::None,
|
||||
true,
|
||||
);
|
||||
let mut clos = Closure {
|
||||
body: Term::Num(6.0).into(),
|
||||
@ -2416,9 +2401,8 @@ mod tests {
|
||||
let mut stack = Stack::new();
|
||||
stack.push_op_cont(cont, 0, TermPos::None);
|
||||
let mut call_stack = CallStack::new();
|
||||
let mut strict = false;
|
||||
|
||||
clos = continuate_operation(clos, &mut stack, &mut call_stack, &mut strict).unwrap();
|
||||
clos = continuate_operation(clos, &mut stack, &mut call_stack).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
clos,
|
||||
|
@ -346,7 +346,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn some_cont() -> OperationCont {
|
||||
OperationCont::Op1(UnaryOp::IsNum(), TermPos::None, true)
|
||||
OperationCont::Op1(UnaryOp::IsNum(), TermPos::None)
|
||||
}
|
||||
|
||||
fn some_arg_marker() -> Marker {
|
||||
|
Loading…
Reference in New Issue
Block a user