MCPcopy Index your code
hub / github.com/endbasic/endbasic / compile_pending_ops

Function compile_pending_ops

core/src/compiler/exprs.rs:452–569  ·  view source on GitHub ↗

Processes `pending` binary ops from innermost to outermost, using `reg` as the accumulator. This avoids the deep recursion that would arise if we compiled binary op chains by recursing on the lhs.

(
    codegen: &mut Codegen,
    symtable: &mut TempSymtable<'_, '_>,
    reg: Register,
    mut etype: ExprType,
    mut pending: Vec<PendingOp>,
)

Source from the content-addressed store, hash-verified

450/// This avoids the deep recursion that would arise if we compiled binary op chains
451/// by recursing on the lhs.
452fn compile_pending_ops(
453 codegen: &mut Codegen,
454 symtable: &mut TempSymtable<'_, '_>,
455 reg: Register,
456 mut etype: ExprType,
457 mut pending: Vec<PendingOp>,
458) -> Result<ExprType> {
459 while let Some(op) = pending.pop() {
460 match op {
461 PendingOp::Unary(op) => {
462 let result_type = match etype {
463 ExprType::Boolean if op.make_boolean.is_some() => ExprType::Boolean,
464 ExprType::Double if op.make_double.is_some() => ExprType::Double,
465 ExprType::Integer => ExprType::Integer,
466 _ => match op.kind {
467 PendingUnaryKind::Negate => return Err(Error::NotANumber(op.pos, etype)),
468 PendingUnaryKind::Not => {
469 return Err(Error::TypeMismatch(op.pos, etype, ExprType::Integer));
470 }
471 },
472 };
473 match result_type {
474 ExprType::Boolean => {
475 let mut scope = symtable.temp_scope();
476 let temp = scope.alloc().map_err(|e| Error::from_syms(e, op.pos))?;
477 codegen.emit_value(temp, ConstantDatum::Integer(1), op.pos)?;
478 codegen.emit(op.make_boolean.unwrap()(reg, reg, temp), op.pos);
479 }
480 ExprType::Double => {
481 codegen.emit(op.make_double.unwrap()(reg), op.pos);
482 }
483 ExprType::Integer => {
484 codegen.emit((op.make_integer)(reg), op.pos);
485 }
486 ExprType::Text => unreachable!(),
487 }
488 etype = result_type;
489 }
490 PendingOp::Binary(op) => {
491 let rpos = op.rhs.start_pos();
492 let mut scope = symtable.temp_scope();
493 let rtemp = scope.alloc().map_err(|e| Error::from_syms(e, rpos))?;
494 let rtype = compile_expr(codegen, symtable, rtemp, op.rhs)?;
495
496 let result_type = match (etype, rtype) {
497 (ExprType::Boolean, ExprType::Boolean) if op.make_boolean.is_some() => {
498 ExprType::Boolean
499 }
500 (ExprType::Text, ExprType::Text) if op.make_text.is_some() => ExprType::Text,
501 (_, _) if op.make_double.is_some() => {
502 match resolve_numeric_binary_type(
503 codegen, reg, etype, rtemp, rtype, rpos, op.pos,
504 ) {
505 Some(v) => v,
506 None => {
507 return Err(Error::BinaryOpType(op.pos, op.op_name, etype, rtype));
508 }
509 }

Callers 1

compile_exprFunction · 0.85

Calls 7

compile_exprFunction · 0.85
temp_scopeMethod · 0.80
allocMethod · 0.80
emit_valueMethod · 0.80
emitMethod · 0.80
start_posMethod · 0.80

Tested by

no test coverage detected