scheme4r 0.2.3

Scheme interpreter for rust
Documentation
use std::{cell::RefCell, rc::Rc};

use crate::runtime::Value;

pub type RecordTypeRef = Rc<RecordType>;
pub type RecordRef = Rc<RefCell<RecordInstance>>;

#[derive(Clone, Debug)]
pub struct RecordFieldSpec {
    name: String,
    mutable: bool,
}

impl RecordFieldSpec {
    pub fn new(name: impl Into<String>, mutable: bool) -> Self {
        Self {
            name: name.into(),
            mutable,
        }
    }

    pub fn name(&self) -> &str {
        self.name.as_str()
    }

    pub fn is_mutable(&self) -> bool {
        self.mutable
    }
}

#[derive(Clone, Debug)]
pub struct RecordType {
    name: String,
    fields: Vec<RecordFieldSpec>,
}

impl RecordType {
    pub fn new(name: impl Into<String>, fields: Vec<RecordFieldSpec>) -> RecordTypeRef {
        Rc::new(Self {
            name: name.into(),
            fields,
        })
    }

    pub fn name(&self) -> &str {
        self.name.as_str()
    }

    pub fn field_count(&self) -> usize {
        self.fields.len()
    }

    pub fn field_name(&self, index: usize) -> Option<&str> {
        self.fields.get(index).map(RecordFieldSpec::name)
    }

    pub fn field_mutable(&self, index: usize) -> Option<bool> {
        self.fields.get(index).map(RecordFieldSpec::is_mutable)
    }
}

#[derive(Clone, Debug)]
pub struct RecordInstance {
    record_type: RecordTypeRef,
    fields: Vec<Value>,
}

impl RecordInstance {
    pub fn new(record_type: RecordTypeRef, fields: Vec<Value>) -> RecordRef {
        Rc::new(RefCell::new(Self {
            record_type,
            fields,
        }))
    }

    pub fn record_type(&self) -> RecordTypeRef {
        self.record_type.clone()
    }

    pub fn field(&self, index: usize) -> Option<&Value> {
        self.fields.get(index)
    }

    pub fn set_field(&mut self, index: usize, value: Value) -> bool {
        if let Some(slot) = self.fields.get_mut(index) {
            *slot = value;
            true
        } else {
            false
        }
    }
}