1
1
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:
Yann Hamdaoui 2021-11-09 12:16:59 +01:00 committed by GitHub
commit 9856905253
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 41 deletions

View File

@ -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

View File

@ -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,

View File

@ -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 {