use std::sync::Arc;
use crate::{
CORE_TABLE_CLASS_ID, ClassRef, Cx, DefaultFactory, Expr, Factory, Fixity, Object, Result,
Symbol, Value,
};
use super::types::PrattTable;
#[derive(Clone)]
pub struct PrattTableObject {
pub symbol: Symbol,
pub table: PrattTable,
}
impl PrattTableObject {
pub fn new(symbol: Symbol, table: PrattTable) -> Self {
Self { symbol, table }
}
}
impl Object for PrattTableObject {
fn display(&self, _cx: &mut Cx) -> Result<String> {
Ok(format!("#<pratt-table {}>", self.symbol))
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
impl crate::ObjectCompat for PrattTableObject {
fn class(&self, cx: &mut Cx) -> Result<ClassRef> {
if let Some(value) = cx
.registry()
.class_by_symbol(&Symbol::qualified("core", "Table"))
{
return Ok(value.clone());
}
cx.factory()
.class_stub(CORE_TABLE_CLASS_ID, Symbol::qualified("core", "Table"))
}
fn as_expr(&self, _cx: &mut Cx) -> Result<Expr> {
Ok(Expr::Symbol(self.symbol.clone()))
}
fn as_table(&self, cx: &mut Cx) -> Result<Value> {
let operators = self
.table
.operators()
.into_iter()
.map(|operator| {
cx.factory().table(vec![
(Symbol::new("symbol"), cx.factory().symbol(operator.symbol)?),
(
Symbol::new("fixity"),
cx.factory().string(
match operator.fixity {
Fixity::Prefix => "prefix",
Fixity::InfixLeft => "infix-left",
Fixity::InfixRight => "infix-right",
Fixity::Postfix => "postfix",
Fixity::Mixfix => "mixfix",
}
.to_owned(),
)?,
),
(
Symbol::new("left-bp"),
cx.factory().number_literal(
Symbol::qualified("numbers", "f64"),
operator.left_bp.to_string(),
)?,
),
(
Symbol::new("right-bp"),
cx.factory().number_literal(
Symbol::qualified("numbers", "f64"),
operator.right_bp.to_string(),
)?,
),
])
})
.collect::<Result<Vec<_>>>()?;
cx.factory().table(vec![
(
Symbol::new("symbol"),
cx.factory().symbol(self.symbol.clone())?,
),
(Symbol::new("operators"), cx.factory().list(operators)?),
])
}
}
pub fn pratt_table_value(symbol: Symbol, table: PrattTable) -> Value {
DefaultFactory
.opaque(Arc::new(PrattTableObject::new(symbol, table)))
.expect("pratt table object should always be boxable")
}