1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

use std::fmt;
use super::constant_value::ConstantValue;
use super::instruction::Instruction;
use super::operand::{ConstantKey, FunctionKey};

/// Compiled function
#[derive(Debug)]
pub struct Procedure {
  pub bytecode: Vec<Instruction>,
  pub register_count: usize,
  pub max_args: usize,
  pub constants: Vec<ConstantValue>,
  pub functions: Vec<String>,
}

impl fmt::Display for Procedure {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    writeln!(f, "registers: {}", self.register_count)?;
    writeln!(f, "arg count: {}", self.max_args)?;
    if self.constants.is_empty() {
      writeln!(f, "constant table: (empty)")?;
    } else {
      writeln!(f, "constant table:")?;
      for (constant_key, constant_value) in self.constants.iter().enumerate() {
        let constant_key = ConstantKey(constant_key as u8);
        writeln!(f, "{constant_key:>4}: {constant_value:<}")?;
      }
    }
    if self.functions.is_empty() {
      writeln!(f, "function table: (empty)")?;
    } else {
      writeln!(f, "function table:")?;
      for (function_key, function_name) in self.functions.iter().enumerate() {
        let function_key = FunctionKey(function_key as u8);
        writeln!(f, "{function_key:>4}: {function_name:?}")?;
      }
    }
    writeln!(f, "bytecode:")?;
    for (ip, instruction) in self.bytecode.iter().enumerate() {
      writeln!(f, "  {ip:>4}  {instruction}")?;
    }
    Ok(())
  }
}