use std::sync::Arc;
use tishlang_core::Value;
#[derive(Debug, Clone)]
pub enum Constant {
Number(f64),
String(Arc<str>),
Bool(bool),
Null,
Closure(usize),
}
impl Constant {
pub fn to_value(&self) -> Value {
match self {
Constant::Number(n) => Value::Number(*n),
Constant::String(s) => Value::String(Arc::clone(s)),
Constant::Bool(b) => Value::Bool(*b),
Constant::Null => Value::Null,
Constant::Closure(_) => {
unreachable!("Closure constant should be handled by VM")
}
}
}
}
#[derive(Debug, Clone)]
pub struct Chunk {
pub code: Vec<u8>,
pub constants: Vec<Constant>,
pub names: Vec<Arc<str>>,
pub nested: Vec<Chunk>,
pub rest_param_index: u16,
pub param_count: u16,
}
impl Chunk {
pub fn new() -> Self {
Self {
code: Vec::new(),
constants: Vec::new(),
names: Vec::new(),
nested: Vec::new(),
rest_param_index: super::NO_REST_PARAM,
param_count: 0,
}
}
pub fn write_u8(&mut self, b: u8) {
self.code.push(b);
}
pub fn write_u16(&mut self, n: u16) {
self.code.extend_from_slice(&n.to_be_bytes());
}
pub fn add_constant(&mut self, c: Constant) -> u16 {
let idx = self.constants.len();
self.constants.push(c);
idx as u16
}
pub fn add_name(&mut self, name: Arc<str>) -> u16 {
if let Some(idx) = self.names.iter().position(|n| n.as_ref() == name.as_ref()) {
return idx as u16;
}
let idx = self.names.len();
self.names.push(name);
idx as u16
}
pub fn add_nested(&mut self, chunk: Chunk) -> usize {
let idx = self.nested.len();
self.nested.push(chunk);
idx
}
}
impl Default for Chunk {
fn default() -> Self {
Self::new()
}
}