cas_compiler/expr/
product.rs1use cas_compute::{numerical::value::Value, primitive::int};
2use cas_error::Error;
3use cas_parser::parser::{ast::{Product, RangeKind}, token::op::BinOpKind};
4use crate::{item::Symbol, Compile, Compiler, InstructionKind};
5
6impl Compile for Product {
7 fn compile(&self, compiler: &mut Compiler) -> Result<(), Error> {
8 compiler.new_scope(|compiler| {
27 compiler.add_instr(InstructionKind::LoadConst(Value::Integer(int(1))));
29
30 let chunk = compiler.new_chunk_get(|compiler| {
33 self.range.end.compile(compiler)
34 })?;
35
36 self.range.start.compile(compiler)?;
38 let symbol_id = compiler.add_symbol(&self.variable)?;
39 compiler.add_instr(InstructionKind::AssignVar(symbol_id));
40
41 let condition_start = compiler.new_end_label();
44 compiler.add_instr(InstructionKind::LoadVar(Symbol::User(symbol_id)));
45 compiler.add_chunk_instrs(chunk);
46 match self.range.kind {
47 RangeKind::HalfOpen => compiler.add_instr(InstructionKind::Binary(BinOpKind::Less)),
48 RangeKind::Closed => compiler.add_instr(InstructionKind::Binary(BinOpKind::LessEq)),
49 }
50
51 let loop_end = compiler.new_unassociated_label();
52 compiler.add_instr(InstructionKind::JumpIfFalse(loop_end));
53
54 self.body.compile(compiler)?;
56 compiler.add_instr(InstructionKind::Binary(BinOpKind::Mul));
57
58 compiler.add_instr(InstructionKind::LoadVar(Symbol::User(symbol_id)));
60 compiler.add_instr(InstructionKind::LoadConst(Value::Integer(int(1))));
61 compiler.add_instr(InstructionKind::Binary(BinOpKind::Add));
62 compiler.add_instr(InstructionKind::AssignVar(symbol_id));
63
64 compiler.add_instr(InstructionKind::Jump(condition_start));
65
66 compiler.set_end_label(loop_end);
67 Ok(())
68 })?;
69 Ok(())
70 }
71}