use crate::*;
pub struct Arena<T> {
data: RefCell<Vec<Rc<T>>>,
}
impl<T> Arena<T> {
pub fn new() -> Self {
Self {
data: RefCell::new(vec![]),
}
}
pub fn allocate(&self, value: T) -> Weak<T> {
let obj = Rc::new(value);
self.data.borrow_mut().push(obj.clone());
Rc::downgrade(&obj)
}
}
pub struct LmtFactory {
arena: Arena<Symbol1>,
}
impl LmtFactory {
pub fn new() -> Self {
Self {
arena: Arena::new(),
}
}
pub fn create_smtype_slot(&self, name: String) -> Symbol {
Symbol(self.arena.allocate(Symbol1::SmTypeSlot(Rc::new(SmTypeSlot1 {
name,
inherits: RefCell::new(None),
subtypes: shared_array![],
fields: shared_map![],
methods: shared_map![],
method_output: Rc::new(RefCell::new(proc_macro2::TokenStream::new())),
}))))
}
pub fn create_field_slot(&self, is_ref: bool, name: String, field_type: syn::Type, field_init: syn::Expr) -> Symbol {
Symbol(self.arena.allocate(Symbol1::FieldSlot(Rc::new(FieldSlot1 {
is_ref,
name,
field_type,
field_init,
}))))
}
pub fn create_method_slot(&self, name: String, defined_in: Symbol, doc_attribute: Vec<syn::Attribute>) -> Symbol {
Symbol(self.arena.allocate(Symbol1::MethodSlot(Rc::new(MethodSlot1 {
name,
defined_in,
doc_attribute: RefCell::new(doc_attribute),
override_logic_mapping: SharedMap::new(),
}))))
}
}
#[derive(Clone)]
pub struct Symbol(Weak<Symbol1>);
impl Eq for Symbol {}
impl PartialEq for Symbol {
fn eq(&self, other: &Self) -> bool {
self.0.ptr_eq(&other.0)
}
}
impl Hash for Symbol {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.as_ptr().hash(state)
}
}
macro_rules! access {
($symbol:expr) => { $symbol.0.upgrade().unwrap().as_ref() };
}
impl Symbol {
pub fn is_smtype_slot(&self) -> bool {
matches!(access!(self), Symbol1::SmTypeSlot(_))
}
pub fn is_field_slot(&self) -> bool {
matches!(access!(self), Symbol1::FieldSlot(_))
}
pub fn is_method_slot(&self) -> bool {
matches!(access!(self), Symbol1::MethodSlot(_))
}
pub fn name(&self) -> String {
match access!(self) {
Symbol1::SmTypeSlot(slot) => slot.name.clone(),
Symbol1::FieldSlot(slot) => slot.name.clone(),
Symbol1::MethodSlot(slot) => slot.name.clone(),
}
}
pub fn inherits(&self) -> Option<Symbol> {
match access!(self) {
Symbol1::SmTypeSlot(slot) => slot.inherits.borrow().clone(),
_ => panic!(),
}
}
pub fn set_inherits(&self, value: Option<&Symbol>) {
match access!(self) {
Symbol1::SmTypeSlot(slot) => {
slot.inherits.replace(value.map(|v| v.clone()));
},
_ => panic!(),
}
}
pub fn asc_smtype_list(&self) -> Vec<Symbol> {
let mut out = vec![self.clone()];
let mut m = self.inherits();
while let Some(m1) = m {
out.insert(0, m1.clone());
m = m1.inherits();
}
out
}
pub fn create_layers_over_weak_root(base: &str, asc_smtype_list: &[Symbol]) -> String {
let mut layers = String::new();
let mut parens = 0usize;
for m in asc_smtype_list.iter().rev() {
let m_name = m.name();
layers.push_str(&format!("{m_name}("));
parens += 1;
}
layers.push_str(base);
layers.push_str(".clone()");
layers.push_str(&")".repeat(parens));
return layers;
}
pub fn lookup_method_in_base_smtype(&self, name: &str) -> Option<Symbol> {
let mut m = self.clone();
while let Some(m1) = m.inherits() {
let mt = m1.methods().get(&name.to_owned());
if let Some(mt) = mt {
return Some(mt);
}
m = m1;
}
None
}
pub fn subtypes(&self) -> SharedArray<Symbol> {
match access!(self) {
Symbol1::SmTypeSlot(slot) => slot.subtypes.clone(),
_ => panic!(),
}
}
pub fn fields(&self) -> SharedMap<String, Symbol> {
match access!(self) {
Symbol1::SmTypeSlot(slot) => slot.fields.clone(),
_ => panic!(),
}
}
pub fn methods(&self) -> SharedMap<String, Symbol> {
match access!(self) {
Symbol1::SmTypeSlot(slot) => slot.methods.clone(),
_ => panic!(),
}
}
pub fn method_output(&self) -> Rc<RefCell<proc_macro2::TokenStream>> {
match access!(self) {
Symbol1::SmTypeSlot(slot) => slot.method_output.clone(),
_ => panic!(),
}
}
pub fn field_type(&self) -> syn::Type {
match access!(self) {
Symbol1::FieldSlot(slot) => slot.field_type.clone(),
_ => panic!(),
}
}
pub fn field_init(&self) -> syn::Expr {
match access!(self) {
Symbol1::FieldSlot(slot) => slot.field_init.clone(),
_ => panic!(),
}
}
pub fn is_ref(&self) -> bool {
match access!(self) {
Symbol1::FieldSlot(slot) => slot.is_ref.clone(),
_ => panic!(),
}
}
pub fn defined_in(&self) -> Symbol {
match access!(self) {
Symbol1::MethodSlot(slot) => slot.defined_in.clone(),
_ => panic!(),
}
}
pub fn doc_attribute(&self) -> Vec<syn::Attribute> {
match access!(self) {
Symbol1::MethodSlot(slot) => slot.doc_attribute.borrow().clone(),
_ => panic!(),
}
}
pub fn set_doc_attribute(&self, attr: Vec<syn::Attribute>) {
match access!(self) {
Symbol1::MethodSlot(slot) => { slot.doc_attribute.replace(attr); },
_ => panic!(),
}
}
pub fn override_logic_mapping(&self) -> SharedMap<Symbol, Rc<OverrideLogicMapping>> {
match access!(self) {
Symbol1::MethodSlot(slot) => slot.override_logic_mapping.clone(),
_ => panic!(),
}
}
}
impl ToString for Symbol {
fn to_string(&self) -> String {
self.name()
}
}
enum Symbol1 {
SmTypeSlot(Rc<SmTypeSlot1>),
FieldSlot(Rc<FieldSlot1>),
MethodSlot(Rc<MethodSlot1>),
}
struct SmTypeSlot1 {
name: String,
inherits: RefCell<Option<Symbol>>,
subtypes: SharedArray<Symbol>,
fields: SharedMap<String, Symbol>,
methods: SharedMap<String, Symbol>,
method_output: Rc<RefCell<proc_macro2::TokenStream>>,
}
struct FieldSlot1 {
name: String,
field_type: syn::Type,
field_init: syn::Expr,
is_ref: bool,
}
struct MethodSlot1 {
name: String,
defined_in: Symbol,
doc_attribute: RefCell<Vec<syn::Attribute>>,
override_logic_mapping: SharedMap<Symbol, Rc<OverrideLogicMapping>>,
}
pub struct OverrideLogicMapping {
override_code: RefCell<Option<proc_macro2::TokenStream>>,
override_logic_mapping: SharedMap<Symbol, Rc<OverrideLogicMapping>>,
}
impl OverrideLogicMapping {
pub fn new() -> Self {
Self {
override_code: RefCell::new(None),
override_logic_mapping: SharedMap::new(),
}
}
pub fn override_code(&self) -> Option<proc_macro2::TokenStream> {
self.override_code.borrow().clone()
}
pub fn set_override_code(&self, code: Option<proc_macro2::TokenStream>) {
self.override_code.replace(code);
}
pub fn override_logic_mapping(&self) -> SharedMap<Symbol, Rc<OverrideLogicMapping>> {
self.override_logic_mapping.clone()
}
}
#[derive(Clone, Hash, PartialEq, Eq)]
pub struct SmTypeSlot(pub Symbol);
impl Deref for SmTypeSlot {
type Target = Symbol;
fn deref(&self) -> &Self::Target {
assert!(self.0.is_smtype_slot());
&self.0
}
}
#[derive(Clone, Hash, PartialEq, Eq)]
pub struct FieldSlot(pub Symbol);
impl Deref for FieldSlot {
type Target = Symbol;
fn deref(&self) -> &Self::Target {
assert!(self.0.is_field_slot());
&self.0
}
}
#[derive(Clone, Hash, PartialEq, Eq)]
pub struct MethodSlot(pub Symbol);
impl Deref for MethodSlot {
type Target = Symbol;
fn deref(&self) -> &Self::Target {
assert!(self.0.is_method_slot());
&self.0
}
}