///|
// A managed Number-domain multiplicative operation. Runtime owns the complete
// ToPrimitive(number) sequence, final Number operation, and abrupt completion;
// executors supply only already-evaluated operands and the source location.
///|
pub(all) enum ExecutorMultiplicativeOperator {
ExecutorMultiplicativeMultiply
ExecutorMultiplicativeDivide
ExecutorMultiplicativeRemainder
}
///|
pub enum ExecutorCoercingMultiplicativeStart {
ExecutorCoercingMultiplicativeCompleted(Value)
ExecutorCoercingMultiplicativeSuspended(ExecutorCoercingMultiplicativeRequest)
}
///|
pub struct ExecutorCoercingMultiplicativeRequest {
priv left : Value
priv right : Value
priv operator : ExecutorMultiplicativeOperator
priv loc : @token.Loc
}
///|
fn ExecutorCoercingMultiplicativeRequest::ExecutorCoercingMultiplicativeRequest(
left~ : Value,
right~ : Value,
operator~ : ExecutorMultiplicativeOperator,
loc~ : @token.Loc,
) -> ExecutorCoercingMultiplicativeRequest {
{ left, right, operator, loc, }
}
///|
fn finish_multiplicative(
operator : ExecutorMultiplicativeOperator,
left : Value,
right : Value,
_loc : @token.Loc,
interp? : Interpreter? = None,
) -> Value raise Error {
let left_number = to_number(left, interp~)
let right_number = to_number(right, interp~)
match operator {
ExecutorMultiplicativeMultiply => Number(left_number * right_number)
ExecutorMultiplicativeDivide => Number(left_number / right_number)
ExecutorMultiplicativeRemainder => Number(left_number % right_number)
}
}
///|
pub fn begin_executor_coercing_multiplicative(
operator : ExecutorMultiplicativeOperator,
left : Value,
right : Value,
loc : @token.Loc,
) -> ExecutorCoercingMultiplicativeStart raise Error {
if is_js_object(left) || is_js_object(right) {
ExecutorCoercingMultiplicativeSuspended(
ExecutorCoercingMultiplicativeRequest(left~, right~, operator~, loc~),
)
} else {
ExecutorCoercingMultiplicativeCompleted(
finish_multiplicative(operator, left, right, loc),
)
}
}
///|
priv enum ExecutorCoercingMultiplicativePhase {
ExecutorCoercingMultiplicativeNeedLeft
ExecutorCoercingMultiplicativeAwaitLeft(ExecutorToPrimitiveOperation)
ExecutorCoercingMultiplicativeHaveLeft(Double)
ExecutorCoercingMultiplicativeAwaitRight(Double, ExecutorToPrimitiveOperation)
ExecutorCoercingMultiplicativeComplete(Value)
}
///|
priv struct ExecutorCoercingMultiplicativeFrame {
request : ExecutorCoercingMultiplicativeRequest
mut phase : ExecutorCoercingMultiplicativePhase
}
///|
fn ExecutorCoercingMultiplicativeFrame::ExecutorCoercingMultiplicativeFrame(
request : ExecutorCoercingMultiplicativeRequest,
) -> ExecutorCoercingMultiplicativeFrame {
{ request, phase: ExecutorCoercingMultiplicativeNeedLeft, }
}
///|
fn ExecutorCoercingMultiplicativeFrame::finish_right(
self : ExecutorCoercingMultiplicativeFrame,
interp : Interpreter,
left : Double,
right : Value,
) -> ExecutorActivationStep raise Error {
let result = finish_multiplicative(
self.request.operator,
Number(left),
right,
self.request.loc,
interp=Some(interp),
)
self.phase = ExecutorCoercingMultiplicativeComplete(result)
ExecutorActivationNormal(result)
}
///|
fn ExecutorCoercingMultiplicativeFrame::step_frame(
self : ExecutorCoercingMultiplicativeFrame,
interp : Interpreter,
) -> ExecutorActivationStep raise Error {
match self.phase {
ExecutorCoercingMultiplicativeNeedLeft => {
let operation = ExecutorToPrimitiveOperation(
self.request.left,
ExecutorToPrimitiveNumber,
self.request.loc,
)
match operation.step(interp) {
ExecutorActivationNormal(value) => {
let left_number = to_number(value, interp=Some(interp))
self.phase = ExecutorCoercingMultiplicativeHaveLeft(left_number)
self.step_frame(interp)
}
step => {
self.phase = ExecutorCoercingMultiplicativeAwaitLeft(operation)
step
}
}
}
ExecutorCoercingMultiplicativeAwaitLeft(operation) =>
match operation.step(interp) {
ExecutorActivationNormal(value) => {
let left_number = to_number(value, interp=Some(interp))
self.phase = ExecutorCoercingMultiplicativeHaveLeft(left_number)
self.step_frame(interp)
}
step => {
self.phase = ExecutorCoercingMultiplicativeAwaitLeft(operation)
step
}
}
ExecutorCoercingMultiplicativeHaveLeft(left_number) => {
let operation = ExecutorToPrimitiveOperation(
self.request.right,
ExecutorToPrimitiveNumber,
self.request.loc,
)
match operation.step(interp) {
ExecutorActivationNormal(value) =>
self.finish_right(interp, left_number, value)
step => {
self.phase = ExecutorCoercingMultiplicativeAwaitRight(
left_number, operation,
)
step
}
}
}
ExecutorCoercingMultiplicativeAwaitRight(left_number, operation) =>
match operation.step(interp) {
ExecutorActivationNormal(value) =>
self.finish_right(interp, left_number, value)
step => {
self.phase = ExecutorCoercingMultiplicativeAwaitRight(
left_number, operation,
)
step
}
}
ExecutorCoercingMultiplicativeComplete(value) => {
ignore(value)
raise @errors.InternalError(
message="coercing multiplicative frame stepped after completion",
)
}
}
}
///|
impl ExecutorActivationFrame for ExecutorCoercingMultiplicativeFrame with fn step(
self,
interp,
) {
self.step_frame(interp)
}
///|
impl ExecutorActivationFrame for ExecutorCoercingMultiplicativeFrame with fn deliver_activation_completion(
self,
completion,
) {
match self.phase {
ExecutorCoercingMultiplicativeAwaitLeft(operation)
| ExecutorCoercingMultiplicativeAwaitRight(_, operation) =>
operation.deliver_activation_completion(completion)
ExecutorCoercingMultiplicativeNeedLeft
| ExecutorCoercingMultiplicativeHaveLeft(_)
| ExecutorCoercingMultiplicativeComplete(_) =>
raise @errors.InternalError(
message="coercing multiplicative received an unexpected child completion",
)
}
}